<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dr Nic &#187; Javascript</title>
	<atom:link href="http://drnicwilliams.com/category/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://drnicwilliams.com</link>
	<description>Ruby makes Rails, Javascript makes Ajax, Dr Nic makes Magic</description>
	<lastBuildDate>Mon, 21 May 2012 03:31:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Showcase of CoffeeScript &#8211; 2.5 mins for your next Dev Group meeting</title>
		<link>http://drnicwilliams.com/2010/05/28/showcase-of-coffeescript-2-5-mins-for-your-next-dev-group-meeting/</link>
		<comments>http://drnicwilliams.com/2010/05/28/showcase-of-coffeescript-2-5-mins-for-your-next-dev-group-meeting/#comments</comments>
		<pubDate>Fri, 28 May 2010 12:20:08 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mocra]]></category>
		<category><![CDATA[Speaking]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=733</guid>
		<description><![CDATA[If you are giving an &#8220;Introduction to CoffeeScript&#8221; talk at your local developer group in the future, I have a 2:30min video you might find exciting to show. CoffeeScript is so cool that I thought it really needed to be put to music. Hard rock music. AC/DC. I finished my session at NordicRuby with this [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>
<object id="sample-video" class="alignright" style="float: right" width="320" height="195" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab"><param name="src" value="http://s3.amazonaws.com/screencasts.drnicwilliams/Summary%20of%20CoffeeScript%20-%20streaming.mov" /><param name='autoplay' value="false" /><param name='controller' value="true" /><param name='loop' value="false" /><embed src="http://s3.amazonaws.com/screencasts.drnicwilliams/Summary%20of%20CoffeeScript%20-%20streaming.mov" width="320" height="195" controller="true" autoplay="false" loop="false" scale="tofit" cache="true" pluginspage="http://www.apple.com/quicktime/download/"></embed></object></p>
<p>If you are giving an &#8220;Introduction to CoffeeScript&#8221; talk at your local developer group in the future, I have a 2:30min video you might find exciting to show. <a href="http://coffeescript.org/" target="_blank">CoffeeScript</a> is so cool that I thought it really needed to be put to music. Hard rock music. AC/DC.</p>
<p>I finished my session at <a href="http://nordicruby.com" target="_blank">NordicRuby</a> with this video and I think it helped get lots of people excited about CoffeeScript.</p>
<p>Because of it&#8217;s heavy dependence of the backing song &#8211; the screencast is boring without it &#8211; I&#8217;m kind of screwed as to how to distribute it to other presenters. The licensing rules of including music and it&#8217;s 600Mb size are prohibitive.</p>
<p>What the hell. I&#8217;ve included an inline sample above; and the links to the 600Mb version is below. All self-promotional &#8220;Dr Nic made this shiny video&#8221; bits have been removed. Go for gold. Share the CoffeeScript excitement.</p>
<h3 id="nordicruby">NordicRuby</h3>
<p><a href="http://nordicruby.com">NordicRuby</a> finished 5 days ago, but many of the attendees and speakers are only finally winding down. Executed with the style, excitement and pizazz of Unspace&#8217;s RubyFringe and FutureRuby conferences, I had a brilliant time in Gothenburg. If NordicRuby&#8217;s organiser&#8217;s <a href="http://elabs.se/">Elabs</a> host the event again in 2011 I highly recommend attending. Carefully selected and sequenced speakers from around the world, 30 minute talks with 30 minute breaks over two days, an hour of lightning talks each day, and parties every night. Phew.</p>
<p>To CJ and Lilly, the organisers, the other speakers and all the attendees, thanks for an awesome experience in Sweden. Looking forward to coming back next year.</p>
<h3 id="why_coffeescript">Why CoffeeScript?</h3>
<p>JavaScript has a wonderful feature or two: it&#8217;s everywhere and it&#8217;s getting really fast. Unfortunately, its syntax was heavily influenced by Java/C++ and other popular goliaths of the time. But the JavaScript runtime is sweet. JavaScript syntax, not so sweet. </p>
<p>Like .NET and it&#8217;s selection of languages, the JVM and it&#8217;s growing smorgasbord of languages, I think the JavaScript runtime could benefit from more experimentation with alternate languages and/or syntaxes. Objective-J was one attempt. CoffeeScript is another.</p>
<p>Of the two, I like CoffeeScript. A lot.</p>
<h3 id="demonstrating_coffeescript_at_dev_meetups">Demonstrating CoffeeScript at Dev meetups</h3>
<p>The video flies through core ideas pretty quickly, so I ran through syntax examples on a slide first, and then said &#8220;You know, I think this would go better to music,&#8221; and played the video.</p>
<p><img src="http://img.skitch.com/20100528-cf2ts4uqmn91dy8h7m7hj26iwy.png" width="500px"></p>
<h3 id="download_and_demo">Download and Demo</h3>
<p>The purpose of offering the 600Mb video version is for the growing number of people doing CoffeeScript talks at their local software dev groups. The music in it is not licensed, not mine, but sounds awesome.</p>
<p>Please play the video with speakers. AC/DC on mute is a cruel act. Also watching the text jump around without the music is probably weird to watch. AC/DC and CoffeeScript. Perfect match, I think.</p>
<p><a href="http://s3.amazonaws.com/screencasts.drnicwilliams/Summary%20of%20CoffeeScript%20-%20Dr%20Nic%20-%20Mocra.mov?torrent"><img src="http://s3.amazonaws.com/screencasts.drnicwilliams/Summary%20of%20CoffeeScript%20cover.png" width="500px"></a></p>
<p>Formats: <a href="http://s3.amazonaws.com/screencasts.drnicwilliams/Summary%20of%20CoffeeScript%20-%20Dr%20Nic%20-%20Mocra.mov?torrent">Torrent</a> | <a href="http://s3.amazonaws.com/screencasts.drnicwilliams/Summary%20of%20CoffeeScript%20-%20Dr%20Nic%20-%20Mocra.mov">Download</a> (600Mb)</p>
<h3 id="tack_s_mycket">Tack så mycket</h3>
<p>Swedish for &#8220;Thank you very much,&#8221; pronounced like &#8220;tuck sa-meekeh&#8221; or thereabouts.</p>
<p>If you use the video at all, I&#8217;d really appreciate it if you left a comment below! </p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2010/05/28/showcase-of-coffeescript-2-5-mins-for-your-next-dev-group-meeting/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
<enclosure url="http://s3.amazonaws.com/screencasts.drnicwilliams/Summary%20of%20CoffeeScript%20-%20streaming.mov" length="2832999" type="video/quicktime" />
<enclosure url="http://s3.amazonaws.com/screencasts.drnicwilliams/Summary%20of%20CoffeeScript%20-%20Dr%20Nic%20-%20Mocra.mov" length="599670164" type="video/quicktime" />
		</item>
		<item>
		<title>Using CoffeeScript in Rails and even on Heroku</title>
		<link>http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/</link>
		<comments>http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 12:46:52 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mocra]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=713</guid>
		<description><![CDATA[I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for pure JavaScript. What is CoffeeScript? Imagine all the syntactical delights of Ruby and Haml for your JavaScript. You write in a nice language, but get normal JavaScript at runtime. All whilst having full access to 3rd-party JavaScript libraries (jQuery, PrototypeJS), debugging support (it becomes pure, [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2012/04/10/instant-new-rails-applications-with-the-app-scrolls/' rel='bookmark' title='Permanent Link: Instant new Rails applications with the App Scrolls'>Instant new Rails applications with the App Scrolls</a> <small>When I start a new project I want to start...</small></li><li><a href='http://drnicwilliams.com/2010/06/01/validate-and-save-your-ruby-in-textmate-with-secret-rubinus-superpowers/' rel='bookmark' title='Permanent Link: Validate and Save your Ruby in TextMate &#8211; with secret Rubinus superpowers'>Validate and Save your Ruby in TextMate &#8211; with secret Rubinus superpowers</a> <small>In some TextMate bundles, if you save a file it...</small></li><li><a href='http://drnicwilliams.com/2010/05/28/showcase-of-coffeescript-2-5-mins-for-your-next-dev-group-meeting/' rel='bookmark' title='Permanent Link: Showcase of CoffeeScript &#8211; 2.5 mins for your next Dev Group meeting'>Showcase of CoffeeScript &#8211; 2.5 mins for your next Dev Group meeting</a> <small> If you are giving an &#8220;Introduction to CoffeeScript&#8221; talk...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pretty excited about <a href="http://jashkenas.github.com/coffee-script/">CoffeeScript</a> as a clean-syntax replacement for pure JavaScript. </p>
<h3 id="what_is_coffeescript">What is CoffeeScript?</h3>
<p><img src="http://img.skitch.com/20100315-mq3h882gd6742tixy78mnbc5jt.png" width="550px"></p>
<p>Imagine all the syntactical delights of Ruby and Haml for your JavaScript. You write in a nice language, but get normal JavaScript at runtime. All whilst having full access to 3rd-party JavaScript libraries (jQuery, PrototypeJS), debugging support (it becomes pure, readable JavaScript), existing support from test suites (it&#8217;s normal JavaScript) and growing support from various text editors (<a href="http://github.com/jashkenas/coffee-script-tmbundle">TextMate</a>, <a href="http://github.com/jashkenas/coffee-script/blob/master/extras/coffee.vim">Vim</a>, <a href="http://github.com/defunkt/coffee-mode">Emacs</a>).</p>
<p>What simple delights?</p>
<p>No trailing semi-colons. No <code>{ some_code() }</code> function/closure brackets. String interpolation. Multi-line strings. Explicit <code>class</code> syntax. Array slicing. An existential ? operator.</p>
<p>Scroll down the <a href="http://jashkenas.github.com/coffee-script/">home page</a> for awesome example after example.</p>
<p>These aren&#8217;t library extensions. This is clean, purposeful syntax.</p>
<p>You can play with the joyful syntax of CoffeeScript on the website. After reading the basic examples on the <a href="http://jashkenas.github.com/coffee-script/">CoffeeScript home page</a>, press &#8220;TRY COFFEESCRIPT&#8221; in the header menu.</p>
<p>As you play with the syntax, the equivalent JavaScript is printed on the right hand side (see image above).</p>
<p>How nice is that syntax? Very.</p>
<h3 id="installing_coffeescript">Installing CoffeeScript</h3>
<ol>
<li>Install NodeJS</li>
<li>Install CoffeeScript</li>
</ol>
<p>For NodeJS (<a href="http://nodejs.org/#download">get latest release URL</a>; using 0.1.31 as 0.1.32 doesn&#8217;t unpack for me):</p>
<pre><code>cd /usr/local/src
wget http://nodejs.org/dist/node-v0.1.31.tar.gz
tar xfv node-v0.1.31.tar.gz
cd node-v0.1.31
./configure
make
sudo make install
</code></pre>
<p>For CoffeeScript (<a href="http://jashkenas.github.com/coffee-script/#installation">get latest release URL</a>):</p>
<pre><code>cd /usr/local/src
wget http://github.com/jashkenas/coffee-script/tarball/0.5.5
tar xfv jashkenas-coffee-script-bcf7b3f.tar.gz
cd jashkenas-coffee-script-bcf7b3f
sudo bin/cake install
</code></pre>
<p>Now test that everything is in place:</p>
<pre><code>$ coffee --version
CoffeeScript version 0.5.5
$ coffee -e "sys: require 'sys'; sys.puts 'hello world\n'"
hello world
</code></pre>
<p>Phew!</p>
<p>Note, in the command-line/on the server, you are using the NodeJS JavaScript environment. It supports the <a href="http://commonjs.org/">CommonJS</a> API for loading modules (normal JavaScript: <code>var sys = require('sys')</code>).</p>
<h3 id="um_but_how_do_i_use_it_in_my_web_app">Um, but how do I use it in my web app?</h3>
<p>Your application source code will have <code>*.coffee</code> files containing your sexy, short CoffeeScript. But at runtime, the browser needs the generated JavaScript.</p>
<p>I&#8217;ve been using the Jonas Nicklas&#8217; <a href="http://github.com/jnicklas/bistro_car">bistro_car</a> gem:</p>
<pre><code>gem install bistro_car
mkdir -p app/scripts
</code></pre>
<p>In your Rails <code>config/environment.rb</code> file, add:</p>
<pre><code>config.gem 'bistro_car'
</code></pre>
<p>And in your layouts, such as <code>app/views/layouts/application.html.erb</code> add to the <code>&lt;head&gt;</code> or the bottom:</p>
<pre><code>&lt;%= coffee_script_bundle %&gt;
</code></pre>
<p>Now you&#8217;re good to go. Add your CoffeeScript files in <code>app/scripts/*.coffee</code> and they will be automatically available as JavaScript.</p>
<h3 id="warning_check_your_version_of_coffeescript">WARNING: Check your version of CoffeeScript</h3>
<p>Check that this hasn&#8217;t happened:</p>
<pre><code>$ coffee --version
CoffeeScript version 0.3.2
$ which coffee
/usr/bin/coffee
</code></pre>
<p>Arrgh, we should be using <code>/usr/local/bin/coffee</code>. <code>bistro_car</code> currently installs the old rubygem-based version of coffee-script; and you might be unlucky to have your $PATH find the wrong one first.</p>
<p>Either delete it (<code>sudo rm /usr/bin/coffee</code> and restart your shell) or make sure <code>/usr/local/bin</code> is earlier in your <code>$PATH</code> than <code>/usr/bin</code>, where RubyGems installed the old, unnecessary version of <code>coffee</code> command.</p>
<h3 id="let8217s_drink_the_coffeescript">Let&#8217;s drink the CoffeeScript</h3>
<p>Create a file <code>app/scripts/application.coffee</code> with contents:</p>
<pre><code>powers: [1,2,3,4].map (i) -&gt; i * i
alert powers
</code></pre>
<p>Load up a view in a browser and see <code>[1,4,9,16]</code>. You win! Throw in some jQuery/PrototypeJS/whatever. Beautiful.</p>
<p>View the source of the page, navigate to <code>public/javascripts/bundle/default.js</code> and you&#8217;ll see the generated source:</p>
<pre class="sh_javascript"><code>(function(){
  var powers;
  powers = [1, 2, 3, 4].map(function(i) {
    return i * i;
  });
  alert(powers);
})();
</code></pre>
<h3 id="the_problem_heroku_doesn8217t_have_coffeescript_installed">The problem: Heroku doesn&#8217;t have CoffeeScript installed</h3>
<p>Heroku is a great place to host apps. Though it doesn&#8217;t have CoffeeScript installed so it cannot dynamically convert the <code>*.coffee</code> files into JavaScript.</p>
<p>If you want to use Heroku I guess we need to perform the conversion locally and deploy it.</p>
<p>But. In development and integration testing I want bistro_car&#8217;s dynamically generated <code>default.js</code>. In production, I need a cached version.</p>
<p>In <code>application.html.haml</code> I use (I can&#8217;t keep pretending I use erb):</p>
<pre class="sh_ruby"><code>- if Rails.env.production?
  = javascript_include_tag "coffeescripts"
- else
  = coffee_script_bundle
</code></pre>
<p>Now we&#8217;re just left with the hassle of automatically generating <code>public/javascripts/coffeescripts.js</code>.</p>
<p>First, a rake task. Second, a git pre-commit hook.</p>
<p>Create <code>lib/tasks/bistro_car.rake</code>:</p>
<pre class="sh_ruby"><code>desc "Generate the cached bundle/default.js file from app/scripts/*.coffee files"
task :bistro_car =&gt; :environment do
  path = "public/javascripts/coffeescripts.js"
  puts "Building *.coffee -&gt; #{path}"
  File.open(path, "w") { |file| file &lt;&lt; BistroCar::Bundle.new('default').to_javascript }
end

file "public/javascripts/coffeescripts.js" =&gt; Dir[File.join(Rails.root, 'app/scripts/*.coffee')] do |t|
  Rake::Task["bistro_car"].invoke
end
</code></pre>
<p>Now you can create <code>coffeescripts.js</code> and add it to the repo with:</p>
<pre><code>rake public/javascripts/coffeescripts.js
git add public/javascripts/coffeescripts.js
git commit -m "Initial bundled coffeescripts file"
</code></pre>
<p>Now create <code>.git/hooks/pre-commit</code>:</p>
<pre class="sh_sh"><code>#!/bin/sh

exec rake public/javascripts/coffeescripts.js
</code></pre>
<p>And make it executable (and <code>git commit</code> will invoke it automatically):</p>
<pre><code>chmod +x .git/hooks/pre-commit
</code></pre>
<p>Phew.</p>
<p>Now, whenever you change a *.coffee script and you are about to commit it, the cached-production-only <code>coffeescripts.js</code> is automatically updated and included in the same commit.</p>
<p>Seems like a clean hack.</p>
<h3 id="summary">Summary</h3>
<p>Why not make a library to do this? Well I&#8217;m hoping there is a better, cleaner way. Perhaps <code>bistro_car</code> can include a rails generator to package these bits and pieces itself, if my approach happens to be the best way.</p>
<p>Nonetheless, let history record that CoffeeScript is very cool though in the world of Heroku living with it is non-trivial at the moment.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2012/04/10/instant-new-rails-applications-with-the-app-scrolls/' rel='bookmark' title='Permanent Link: Instant new Rails applications with the App Scrolls'>Instant new Rails applications with the App Scrolls</a> <small>When I start a new project I want to start...</small></li><li><a href='http://drnicwilliams.com/2010/06/01/validate-and-save-your-ruby-in-textmate-with-secret-rubinus-superpowers/' rel='bookmark' title='Permanent Link: Validate and Save your Ruby in TextMate &#8211; with secret Rubinus superpowers'>Validate and Save your Ruby in TextMate &#8211; with secret Rubinus superpowers</a> <small>In some TextMate bundles, if you save a file it...</small></li><li><a href='http://drnicwilliams.com/2010/05/28/showcase-of-coffeescript-2-5-mins-for-your-next-dev-group-meeting/' rel='bookmark' title='Permanent Link: Showcase of CoffeeScript &#8211; 2.5 mins for your next Dev Group meeting'>Showcase of CoffeeScript &#8211; 2.5 mins for your next Dev Group meeting</a> <small> If you are giving an &#8220;Introduction to CoffeeScript&#8221; talk...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Nifty Threaded IM Chat within Gtalk/Gmail Chat</title>
		<link>http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/</link>
		<comments>http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 20:00:54 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mocra]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=550</guid>
		<description><![CDATA[Ever had IM chats where a conversation splits into multiple topics? You&#8217;ll be able to follow along, intelligently piecing together which-message-goes-with-which-topic, until the following scenario inevitably occurs: me: What's on this weekend? Going to the football? me: Are you and Jackie still seeing each other? you: Yes me: Eh? Yes - football or yes to [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/' rel='bookmark' title='Permanent Link: TDD for Greasemonkey scripts; and introducing Ninja Search JS'>TDD for Greasemonkey scripts; and introducing Ninja Search JS</a> <small>&#8220;this article shows how I used test-driven development tools and...</small></li><li><a href='http://drnicwilliams.com/2006/09/11/prototype-call-dollar-on-string/' rel='bookmark' title='Permanent Link: Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)'>Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)</a> <small>The Prototype library gives us the $() operation for converting...</small></li><li><a href='http://drnicwilliams.com/2006/08/29/yehuda-katz-starts-a-blog/' rel='bookmark' title='Permanent Link: Yehuda Katz starts a blog'>Yehuda Katz starts a blog</a> <small>Yehuda is the creator of autoDB &#8211; the wonderful admin...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Ever had IM chats where a conversation splits into multiple topics? You&#8217;ll be able to follow along, intelligently piecing together which-message-goes-with-which-topic, until the following scenario inevitably occurs:</p>
<pre>
  me: What's on this weekend? Going to the football?
  me: Are you and Jackie still seeing each other?
  you: Yes
  me: Eh? Yes - football or yes to Jackie?
</pre>
<p>That is, eventually the messages become ambiguous as to which topic they go to.</p>
<h3 id="the_solution">The solution</h3>
<p><img alt="" src="http://img.skitch.com/20090703-js9ahnd44qmq6ue8ya8fdiryau.preview.jpg" title="Threaded example" class="alignright" width="265" height="311" /></p>
<p>A <a href="http://designbyelle.com/" target="_blank">designer friend of mine</a> and I discovered this problem every day as we talked about different projects and completely unrelated things. Ironically, this led to a new inline topic: <em>what if each thread/topic could be visually identifiable?</em></p>
<p>Perhaps we could just modify one of the HTML-based IM clients, such as Gmail Chat/Gtalk (same could be done for Facebook&#8217;s IM client I guess), and use twitter-esque #tags to identify threads (no fancy jabber protocol changes). If we did this we could prototype something, see if it was a useful way to solve the multi-threaded IM chat problem. <em>I mean, how hard could it be?</em></p>
<h3 id="prototype_greasemonkey_script_firefox_safari">Prototype: Greasemonkey Script (Firefox + Safari)</h3>
<p>Since I have a thing for <a href="https://addons.mozilla.org/en-US/firefox/addon/748">Greasemonkey</a> scripts at the moment (which also run on Safari/<a href="http://mailplaneapp.com/">Mailplane</a> using <a href="http://8-p.info/greasekit/">GreaseKit</a>), it immediately came to mind as a way to hack into Gmail&#8217;s Chat.</p>
<p>After installing Greasemonkey or GreaseKit, <a href="http://drnic.github.com/threaded-gtalk-gmscript/dist/threaded_gtalk.user.js">click to install the extension</a> for Gmail&#8217;s inline Jabber/Gtalk chat.</p>
<p>Restart Gmail, fire up a chat to someone (for example, complain of bugs to <a href="drnicwilliams@gmail.com">drnicwilliams@gmail.com</a>) and try the following:</p>
<pre>
  greasemonkey is fun
  gmailchat is very nifty and hackable
  its cool that I can annotate gmail chat with #greasemonkey
  no way, #gmailchat is colour highlighted
  sexy
</pre>
<p>Which will look something like the picture at the top.</p>
<p>Sadly, I&#8217;m talking to myself here. QA testing can be a lonely man&#8217;s sport.</p>
<h3 id="success">Success?</h3>
<p>Technically, yes. I mean, it works. You use a different #tag and it will be a different colour. </p>
<p>It was a prototype to determine if using #tags was a friendly, non-invasive way to identify threads. And it kind-of works, as long as you remember to use them. In IM, less-so than twitter, it seems unnatural to add #tags, or prefix a keyword with a # character. But, in time, I think you&#8217;d learn to do it to get the benefit.</p>
<p>The bigger issue is that I don&#8217;t want to use Gmail&#8217;s Chat for my IM client. I didn&#8217;t find the source to Apple&#8217;s iChat client lying around on github; and I really don&#8217;t want to go hacking Cocoa/Win32 apps just to try out an idea. A greasemonkey script is an awesome way to try out something like this.</p>
<p>Now, if everyone could just make this idea of #tagging intra-IM conversation threads/topics, then perhaps 5 years from now Apple will pick it up and implement it in iChat. Any of the more accessible, open source clients could implement this too. Probably a lot sooner.</p>
<h3 id="known_bugs">Known bugs</h3>
<p>In Mailplane (though not Safari), the 2nd+ threads aren&#8217;t coloured differently. I&#8217;m having trouble fixing this at the moment due to an <a href="http://github.com/relevance/blue-ridge/issues/#issue/13">issue</a> in <a href="http://github.com/relevance/blue-ridge">blue-ridge</a>&#8217;s setup on Safari.</p>
<p>It currently shares thread colouring across all open chat windows. Probably not a big issue. I forgot to consider multiple chat windows when I wrote the code.</p>
<p>When you use a new #tag, it only finds one previous message with &#8216;tag&#8217; in it. Really, once a word is #tagged, then any message containing &#8216;tagged&#8217; could be included in the thread.</p>
<h3 id="quirky_thing_i_learnt">Quirky thing I learned</h3>
<p>You can&#8217;t really use the <a href="http://docs.jquery.com/Plugins/livequery">jquery.livequery.js</a> plugin to watch for DOM changes in Greasemonkey scripts. It works by hooking into jQuery DOM modification calls, such as <code>append</code> and <code>prepend</code>, to know instantly that something has changed. Gmail, and many other websites, don&#8217;t use jQuery. So it doesn&#8217;t work. Even though your beautiful unit tests say it will. Use <code>setInterval</code> instead.</p>
<h3 id="project_status">Project status</h3>
<p>It&#8217;s finished. It was a prototype to try out an idea. It has unit tests, it works and if you want to use it for your own research project or &#8220;oh oh oh how cool would it be if&#8230;?&#8221; hackathon, go for gold with the code base. Rename it, abuse it. Have fun.</p>
<p>Source on github: <a href="http://github.com/drnic/threaded-gtalk-gmscript/">http://github.com/drnic/threaded-gtalk-gmscript/</a></p>
<h3 id="a_pleasant_word_from_my_sponsor">A pleasant word from my sponsor</h3>
<p>When I was hacking on Threaded Gtalk GMScript, I wasn&#8217;t doing something more productive at my firm <a href="http://mocra.com/">Mocra</a>. Ironically, you could reward my wayward efforts by considering us for your awesome new Rails or iPhone project. It will make you happy. Especially if its chock-full of JavaScript.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/' rel='bookmark' title='Permanent Link: TDD for Greasemonkey scripts; and introducing Ninja Search JS'>TDD for Greasemonkey scripts; and introducing Ninja Search JS</a> <small>&#8220;this article shows how I used test-driven development tools and...</small></li><li><a href='http://drnicwilliams.com/2006/09/11/prototype-call-dollar-on-string/' rel='bookmark' title='Permanent Link: Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)'>Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)</a> <small>The Prototype library gives us the $() operation for converting...</small></li><li><a href='http://drnicwilliams.com/2006/08/29/yehuda-katz-starts-a-blog/' rel='bookmark' title='Permanent Link: Yehuda Katz starts a blog'>Yehuda Katz starts a blog</a> <small>Yehuda is the creator of autoDB &#8211; the wonderful admin...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>TDD for Greasemonkey scripts; and introducing Ninja Search JS</title>
		<link>http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/</link>
		<comments>http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 23:00:40 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mocra]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=523</guid>
		<description><![CDATA[&#8220;this article shows how I used test-driven development tools and processes on a Greasemonkey script.&#8221; Though it also includes free ninjas. When I do online banking I need to select from a large list of other people&#8217;s bank accounts to which I might like to transfer money too. It is the massive drop down list [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/12/dead-simple-javascript-unit-testing-in-rails/' rel='bookmark' title='Permanent Link: Dead simple JavaScript Unit Testing in Rails'>Dead simple JavaScript Unit Testing in Rails</a> <small> Formats: Video/Screencast (410 Mb, torrent) | Video only (vimeo)...</small></li><li><a href='http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/' rel='bookmark' title='Permanent Link: Nifty Threaded IM Chat within Gtalk/Gmail Chat'>Nifty Threaded IM Chat within Gtalk/Gmail Chat</a> <small>Ever had IM chats where a conversation splits into multiple...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><em>&#8220;this article shows how I used test-driven development tools and processes on a Greasemonkey script.&#8221;</em> Though it also includes free ninjas.</p>
<div class="thumbnail"><a href="http://skitch.com/drnic/b19kn/1-long-drop-downs-hate-humans"><img style="width: 200px; float: right;" src="http://img.skitch.com/20090605-fjjyx32iidgw1jtq1kbys8tbr7.preview.jpg" alt="1. Long drop downs hate humans" /></a></div>
<p>When I do online banking I need to select from a large list of other people&#8217;s bank accounts to which I might like to transfer money too. It is the massive drop down list that I must scroll through that I wish to raise issue with today. The problem of having to give other people money is probably a different discussion.</p>
<p>And take those time-zone selector drop down lists, for example, the massively long list rendered by Rails&#8217; <code>time_zone_select</code> helper. Granted, I am thankful for you letting me choose my timezone in your web app. Though for those of us not living in the USA we must hunt for our closest city in the list. Dozens of locations, ordered by time zone and not the name of the city (see adjacent image). Unfortunately you can&#8217;t easily type a few letters of your current city to find it. Rather, you have to scroll. And if you live in the GMT+1000 time zone group (Eastern Australia), you have to scroll all the way to the bottom.</p>
<div class="thumbnail"><a href="http://skitch.com/drnic/b19kx/5-choose-from-a-small-list"><img style="width: 200px; float: right;" alt="5. Choose from a small list" src="http://img.skitch.com/20090605-t82418x1j76w4fm8s44cec9cr3.preview.jpg"/></a></div>
<p>So I got to thinking I&#8217;d like a <a href="http://www.greasespot.net/">Greasemonkey</a> (for Firefox) or <a href="http://8-p.info/greasekit/" title="GreaseKit - User Scripting for all WebKit applications">GreaseKit</a> (for Safari) script that automatically converted all ridiculously long HTML drop down lists into a sexy, autocompletion text field. You could then type in &#8220;bris&#8221; and be presented with &#8220;(GMT+1000) Brisbane&#8221;, or given the less amusing banking scenario then I could type &#8220;ATO&#8221; and get the bank account details for the Australian Tax Office.</p>
<p><strong>I mean, how hard could it be?</strong></p>
<p>This article is two things: an introduction to Ninja Search JS which gives a friendly ninja for every drop down field to solve the above problem. Mostly, the rest of this article shows how I used test-driven development tools and processes on a Greasemonkey script.</p>
<h2 id="introducing_ninja_search_js">Introducing Ninja Search JS</h2>
<div class="thumbnail"><a href="http://drnic.github.com/ninja-search-js/"><img src="http://img.skitch.com/20090606-xy454r3b8u29hsykjs1gfhu259.jpg" alt="Ninja Search JS banner" /></a></div>
<p>Click the banner to learn about and install the awesome Ninja Search JS. It includes free ninjas.</p>
<p>Currently it is a script for Greasemonkey (FireFox) or GreaseKit (Safari). It could be dynamically installed as necessary via a bookmarklet. I just haven&#8217;t done that yet. It could also be a FireFox extension so it didn&#8217;t have to fetch remote CSS and JS assets each time.</p>
<p>Ninja Search JS uses <a href="http://github.com/rmm5t/liquidmetal">liquidmetal</a> and <a href="http://rmm5t.github.com/jquery-flexselect">jquery-flexselect</a> projects created by <a href="http://www.emacsblog.org/">Ryan McGeary</a>.</p>
<p>Most importantly of all, I think, is that I wrote it all using TDD. That is, tests first. I don&#8217;t think this is an erroneous statement given the relatively ridiculous, and unimportant nature of Ninja Search JS itself.</p>
<h2 id="tdd_for_greasemonkey_scripts">TDD for Greasemonkey scripts</h2>
<p>I love the simple idea of Greasemonkey scripts: run a script on a subset of all websites you visit. You can&#8217;t easily do this on desktop apps, which is why web apps are so awesome &#8211; its just HTML inside <em>your</em> browser, and with Greasemoney or browser extensions you can hook into that HTML, add your own DOM, remove DOM, add events etc.</p>
<p>But what stops me writing more of them is that once you cobble together a script, you push it out into the wild and then bug reports start coming back. Or feature requests, preferably. I&#8217;d now have a code base without any test coverage, so each new change is likely to break something else. Its also difficult to isolate bugs across different browsers, or in different environments (running Ninja Search JS in a page that used <a href="http://www.prototypejs.org/">prototypejs</a> originally failed), without a test suite.</p>
<p>And the best way to get yourself a test suite is to write it before you write the code itself. I believe this to be true because I know it sucks writing tests <em>after</em> I&#8217;ve writing the code.</p>
<p>I mostly focused on unit testing this script rather than integration testing. With integration testing I&#8217;d need to install the script into Greasemonkey, then display some HTML, then run the tests. I&#8217;ve no idea how&#8217;d I&#8217;d do that.</p>
<div class="thumbnail"><a href="http://skitch.com/drnic/bunyt/testing-running"><img style="width: 200px; float: right;" src="http://img.skitch.com/20090606-d7usrgr8i1qjs3ji45xfkra3hs.preview.jpg" alt="testing running" /></a></div>
<p>But I do know how to unit test JavaScript, and if I can get good coverage of the core libraries, then I should be able to slap the Greasemonkey specific code on top and do manual QA testing after that. The Greasemonkey specific code shouldn&#8217;t ever change much (it just loads up CSS and more JS code dynamically) so I feel ok about this approach.</p>
<p>For this project I used <a href="http://github.com/nkallen/screw-unit/tree/master">Screw.Unit</a> for the first time (via a modified version of the <a href="http://github.com/relevance/blue-ridge/tree/master">blue-ridge rails plugin</a>) and it was pretty sweet. Especially being able to run single tests or groups of tests in isolation.</p>
<h3 id="project_structure">Project structure</h3>
<div class="thumbnail"><a href="http://skitch.com/drnic/bunbd/summary-of-project-structure"><img src="http://img.skitch.com/20090606-x7h9yhp9s3pt6y86r5q1mm1wf8.jpg" alt="summary of project structure" /></a></div>
<p>All the JavaScript source &#8211; including dependent libraries such as jquery and jquery-flexselect &#8211; was put into the <code>public</code> folder. This is because I needed to be able to load the files into the browser without using <code>file://</code> protocol (which was failing for me). So, I moved the entire project into my Sites folder, and added the project as a Passenger web app. I&#8217;m ahead of myself, but there is a reason I went with <code>public</code> for the JavaScript + assets folder.</p>
<p>In <code>vendor/plugins</code>, The blue-ridge rails plugin is a composite of several JavaScript libraries, including the test framework Screw.Unit, and a headless rake task to run all the tests without browser windows popping up everywhere. In my code base blue-ridge is slightly modified since my project doesn&#8217;t look like a rails app.</p>
<p>Our tests go in <code>spec</code>. In a Rails app using blue-ridge, they&#8217;d go in <code>spec/javascripts</code>, but since JavaScript is all we have in this project I&#8217;ve flattened the spec folder structure.</p>
<p>The <code>website</code> folder houses the github pages website (a git submodule to the gh-pages branch) and also the greasemonkey script and its runtime JavaScript, CSS, and ninja image assets.</p>
<h3 id="a_simple_first_test">A simple first test</h3>
<p>For the Ninja Search JS I wanted to add the little ninja icon next to every <code>&lt;select&gt;</code> element on every page I ever visited. When the icon is clicked, it would convert the corresponding <code>&lt;select&gt;</code> element into a text field with fantastical autocompletion support.</p>
<p>For Screw.Unit, the first thing we need is a <code>spec/ninja_search_spec.js</code> file for the tests, and an HTML fixture file that will be loaded into the browser. The HTML file&#8217;s name must match to the corresponding test name, so it must be <code>spec/fixtures/ninja_search.html</code>.</p>
<p>For our first test we want the cute ninja icon to appear next to <code>&lt;select&gt;</code> drop downs.</p>
<pre lang="javascript">
require("spec_helper.js");
require("../public/ninja_search.js"); // relative to spec folder

Screw.Unit(function(){
  describe("inline activation button", function(){
    it("should display NinjaSearch image button", function(){
      var button = $('a.ninja_search_activation');
      expect(button.size()).to(be_gte, 1);
    });
  });
});
</pre>
<p>The <a href="http://github.com/karnowski/blue-ridge-tmbundle/tree/master">Blue Ridge textmate bundle</a> makes it really easy to create the <code>describe</code> (<code>des</code>) and <code>it</code> (<code>it</code>) blocks, and <code>ex</code> expands into a useful <code>expects(...).to(matcher, ...)</code> snippet.</p>
<p>The two ellipses are values that are compared by a matcher. Matchers are available via global names such as <code>equals</code>, <code>be_gte</code> (greater than or equal) etc. See the <a href="http://github.com/nathansobo/screw-unit/blob/master/javascript/lib/screw/matchers.js">matchers.js</a> file for the default available matchers.</p>
<p>The HTML fixture file is important in that it includes the sample HTML upon which the tests are executed.</p>
<pre lang="html">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;

&lt;head&gt;
  &lt;title&gt;Ninja Search | JavaScript Testing Results&lt;/title&gt;
  &lt;link rel="stylesheet" href="screw.css" type="text/css" charset="utf-8" /&gt;
  &lt;script src="../../vendor/plugins/blue-ridge/lib/blue-ridge.js"&gt;&lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;div&gt;
    &lt;label for="person_user_time_zone_id"&gt;Main drop down for tests&lt;/label&gt;
    &lt;select name="person[user][time_zone_id]" id="person_user_time_zone_id" style="display: inline;"&gt;
      &lt;option value="Hawaii"&gt;(GMT-10:00) Hawaii&lt;/option&gt;
      &lt;option value="Alaska"&gt;(GMT-09:00) Alaska&lt;/option&gt;
      &lt;option value="Pacific Time (US &amp; Canada)"&gt;(GMT-08:00) Pacific Time (US &#038; Canada)&lt;/option&gt;
      &lt;option value="Arizona"&gt;(GMT-07:00) Arizona&lt;/option&gt;
      &lt;option value="Mountain Time (US &amp; Canada)"&gt;(GMT-07:00) Mountain Time (US &#038; Canada)&lt;/option&gt;
      &lt;option value="Central Time (US &amp; Canada)"&gt;(GMT-06:00) Central Time (US &#038; Canada)&lt;/option&gt;
      &lt;option value="Eastern Time (US &amp; Canada)"&gt;(GMT-05:00) Eastern Time (US &#038; Canada)&lt;/option&gt;
    &lt;/select&gt;
  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>In its header it loads the blue-ridge JavaScript library, which in turn loads Screw.Unit and ultimately our spec.js test file (based on corresponding file name), so <code>ninja_search.html</code> will cause a file <code>spec/ninja_search_spec.js</code> to be loaded.</p>
<p>To run our first test just load up the <code>spec/fixtures/ninja_search.html</code> file into your browser.</p>
<p>Your first test will fail. But that&#8217;s ok, that&#8217;s the point of TDD. <a href="http://en.wikipedia.org/wiki/Test-driven_development">Red, green, refactor</a>.</p>
<h3 id="simple_passing_code">Simple passing code</h3>
<p>So now we need some code to make the test pass.</p>
<p>Create a file <code>public/ninja_search.js</code> and something like the following should work:</p>
<pre lang="javascript">
(function($){
  $(function() {
    $('select').each(function(index) {
      var id = $(this).attr('id');

      // create the Ninja Search button, with rel attribute referencing corresponding &gt;select id="...">
      $('&gt; class="ninja_search_activation" rel="' + id + '">ninja search&gt;/a>')
      .insertAfter($(this));
    });
  });
})(jQuery);
</pre>
<p>Reload your test fixtures HTML file and the test should pass.</p>
<p>Now rinse and repeat. The final suite of <a href="http://github.com/drnic/ninja-search-js/tree/master/spec">tests and fixture files</a> for Ninja Search JS are on github.</p>
<h3 id="building_a_greasemonkey_script">Building a Greasemonkey script</h3>
<p>Typically Greasemonkey scripts are all-inclusive affairs. One JavaScript file, named <code>my_script.user.js</code>, typically does the trick.</p>
<p>I decided I wanted a thin Greasemonkey script that would dynamically load my <code>ninja-search.js</code>, and any stylesheets and dependent libraries. This would allow people to install the thin Greasemonkey script once, and I can deploy new versions of the actual code base over time without them having to re-install anything.</p>
<p>Ultimately in production, the stylesheets, images, and JavaScript code would be hosted on the intertubes somewhere. Though during development that would be long-winded and painful to push the code to a remote host just to run tests.</p>
<p>So I have three Greasemonkey scripts:</p>
<ul>
<li><code>public/ninja_search.dev.user.js</code> &#8211; loads each dependent library and asset from the local file system</li>
<li><code>public/ninja_search.local.user.js</code> &#8211; loads compressed library and asset from the local file system</li>
<li><code>public/ninja_search.user.js</code> &#8211; loads compressed library and assets from remote server</li>
</ul>
<p>Let&#8217;s ignore the optimisation of compressing dependent JavaScript libraries for the moment and just look at the <code>dev.user.js</code> and <code>user.js</code> files.</p>
<p>The two scripts differ in the target host from which they load assets and libraries. <a href="http://github.com/drnic/ninja-search-js/blob/master/public/ninja-search.dev.user.js">ninja_search.dev.user.js</a> loads them from the local machine and <a href="http://github.com/drnic/ninja-search-js/blob/master/public/ninja-search.user.js">ninja_search.user.js</a> loads them from a remote server.</p>
<p>For example <code>ninja_search.dev.user.js</code> loads local dependencies like this:</p>
<pre lang="javascript">
require("http://ninja-search-js.local/jquery.js");
require("http://ninja-search-js.local/ninja_search.js");
</pre>
<p>And <code>ninja_search.user.js</code> loads remote dependencies like this:</p>
<pre lang="javascript">
require("http://drnic.github.com/ninja-search-js/dist/jquery.js");
require("http://drnic.github.com/ninja-search-js/dist/ninja_search.js");
</pre>
<p>In the final version of <a href="http://github.com/drnic/ninja-search-js/blob/master/public/ninja-search.user.js">ninja_search.user.js</a> we load a simple, conpressed library containing jquery, our code, and other dependencies, called <a href="http://github.com/drnic/ninja-search-js/blob/master/public/ninja_search_complete.js">ninja_search_complete.js</a>.</p>
<h3 id="using_passenger_to_server_local_libraries">Using Passenger to server local libraries</h3>
<p>The problem with loading local JavaScript libraries using the <code>file://</code> protocol, inferred earlier, is that it doesn&#8217;t work. So if I can&#8217;t load libraries using <code>file://</code> then I must use the <code>http://</code> protocol. That means I must route the requests through Apache/Ningx.</p>
<p>Fortunately there is a very simple solution: use <a href="http://www.modrails.com/">Phusion Passenger</a> which serves a &#8220;web app&#8217;s&#8221; <code>public</code> folder automatically. That&#8217;s why all the javascript, CSS and image assets have been placed in a folder <code>public</code> instead of <code>src</code> or <code>lib</code> or <code>javascript</code>.</p>
<p>On my OS X machine, I moved the repository folder into my <code>Sites</code> folder and wired up the folder as a Passenger web app using <a href="http://github.com/alloy/passengerpane/tree/master">PassengerPane</a>. It took 2 minutes and now I had <a href="http://ninja-search.local">http://ninja-search.local</a> as a valid base URL to serve my JavaScript libraries to my Greasemonkey script.</p>
<h3 id="testing_the_greasemonkey_scripts">Testing the Greasemonkey scripts</h3>
<p>I can only have one of the three Greasemonkey scripts installed at a time, so I install the <code>ninja-search.dev.user.js</code> file to check that everything is basically working inside a browser on interesting, foreign sites (outside of the unit test HTML pages).</p>
<p>Once I&#8217;ve deployed the JavaScript files and assets to the remote server I can then install the <code>ninja-search.user.js</code> file (<a href="http://drnic.github.com/ninja-search-js/dist/ninja-search.user.js">so can you</a>) and double check that I haven&#8217;t screwed anything up.</p>
<h3 id="deploying_via_github_pages">Deploying via GitHub Pages</h3>
<p>The normal, community place to upload and share Greasemonkey scripts is <a href="http://userscripts.org/">userscripts.org</a>. This is great for one file scripts, though if your script includes CSS and image assets, let alone additional JavaScript libraries, then I don&#8217;t think its as helpful, which is a pity.</p>
<p>So I decided to deploy the ninja-search-js files into the project&#8217;s own GitHub Pages site.</p>
<p>After creating the GitHub Pages site using <a href="http://github.com/blog/277-pages-generator">Pages Generator</a>, I then pulled down the gh-pages branch, and then linked (via submodules) that branch into my master branch as <code>website</code> folder.</p>
<p>Something like:</p>
<pre><code>
git checkout origin/gh-pages -b gh-pages
git checkout master
git submodule add -b gh-pages git@github.com:drnic/ninja-search-js.git website
</code></pre>
<p>Now I can access the gh-pages branch from my master branch (where the code is).</p>
<p>Then to deploy our Greasemonkey script we just copy over all the <code>public</code> files into <code>website/dist</code>, and then commit and push the changes to the gh-pages branch.</p>
<pre><code>
mkdir -p website/dist
cp -R public/* website/dist/
cd website
git commit -a "latest script release"
git push origin gh-pages
cd ..
</code></pre>
<p>Then you wait very patiently for GitHub to deploy your latest website, which now contains your Greasemonkey script (<code>dist/ninja-search.user.js</code>) and all the libraries (our actual code), stylesheets and images.</p>
<h3 id="summary">Summary</h3>
<p>Greasemonkey scripts might seem like small little chunks of code. But all code starts small and grows. At some stage you&#8217;ll wish you had some test coverage. And later you&#8217;ll hate yourself for ever having release the bloody thing in the first place.</p>
<p>I wrote all this up to summarise how I&#8217;d done TDD for the <a href="http://drnic.github.com/ninja-search-js/">Ninja Search JS</a> project, which is slightly different from how I added test cases to _why&#8217;s <a href="http://github.com/drnic/8cpj/tree/master">the octocat&#8217;s pajamas</a> greasemonkey script when I first started hacking with unit testing Greasemonkey scripts. The next one will probably be slightly different again.</p>
<p>I feel good about the current project structure, I liked Screw.Unit and blue-ridge, and I&#8217;m amused by my use of GitHub Pages to deploy the application itself.</p>
<p>If anyone has any ideas on how this could be improved, or done radically differently, I&#8217;d love to hear them!</p>
<h3 id="polish_your_rails_project_with_mocra">Polish your Rails project with Mocra</h3>
<p>I want to help you, your business, your boss and your project reach delightful levels of wickedly awesomeness. I’m so proud of the small team of ace Rails developers here at Mocra and what I know we can do for you.</p>
<p>Send an email to <a href="mailto:&#x72;&#x61;&#x69;&#x6C;&#x73;&#x40;&#x6D;&#x6F;&#x63;&#x72;&#x61;&#x2E;&#x63;&#x6F;&#x6D;">rails@mocra.com</a> about your current/future projects. Dare us to be more awesome!</p>
<p>While you wait for a reply perhaps you&#8217;d like to learn more about <a href="http://mocra.com/how-we-do-it/">How we do it</a> at <a href="http://mocra.com/">Mocra</a>?</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/12/dead-simple-javascript-unit-testing-in-rails/' rel='bookmark' title='Permanent Link: Dead simple JavaScript Unit Testing in Rails'>Dead simple JavaScript Unit Testing in Rails</a> <small> Formats: Video/Screencast (410 Mb, torrent) | Video only (vimeo)...</small></li><li><a href='http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/' rel='bookmark' title='Permanent Link: Nifty Threaded IM Chat within Gtalk/Gmail Chat'>Nifty Threaded IM Chat within Gtalk/Gmail Chat</a> <small>Ever had IM chats where a conversation splits into multiple...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>To WebKit or not to WebKit within your iPhone app?</title>
		<link>http://drnicwilliams.com/2008/11/10/to-webkit-or-not-to-webkit-within-your-iphone-app/</link>
		<comments>http://drnicwilliams.com/2008/11/10/to-webkit-or-not-to-webkit-within-your-iphone-app/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 13:04:26 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Iphone]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mocra]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=330</guid>
		<description><![CDATA[I know HTML. Its on my CV. Expert level. I also know CSS and a whole bunch of JavaScript. I can even do TDD with JavaScript. And on the iPhone there is this nifty object called UIWebView. Otherwise known as WebKit. Otherwise known as an embedded browser in your iPhone app. And if you want [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2008/11/04/iphone-dev-podcast-about-fmdb-migration-manager-and-rbiphonetest/' rel='bookmark' title='Permanent Link: iPhone dev podcast about fmdb-migration-manager and rbiphonetest'>iPhone dev podcast about fmdb-migration-manager and rbiphonetest</a> <small>Radio is where ugly people go. Podcasts is where ugly,...</small></li><li><a href='http://drnicwilliams.com/2008/07/04/unit-testing-iphone-apps-with-ruby-rbiphonetest/' rel='bookmark' title='Permanent Link: Unit Testing iPhone apps with Ruby: rbiphonetest'>Unit Testing iPhone apps with Ruby: rbiphonetest</a> <small> Everything to love about Ruby: the concise, powerful language;...</small></li><li><a href='http://drnicwilliams.com/2006/09/11/prototype-call-dollar-on-string/' rel='bookmark' title='Permanent Link: Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)'>Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)</a> <small>The Prototype library gives us the $() operation for converting...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://mocra.com/projects/surfreport/"><img class="alignright" src="http://img.skitch.com/20081110-189ta9iaubfwxu1hke3r2rhcb.png" alt="Oakley's Surf Report"/></a></p>
<p>I know HTML. Its on my CV. Expert level. I also know CSS and a whole bunch of JavaScript. I can even do TDD with JavaScript.</p>
<p>And on the iPhone there is this nifty object called <code>UIWebView</code>. Otherwise known as WebKit. Otherwise known as an embedded browser in your iPhone app.</p>
<p>And if you want a sexily awesome looking UI view, like the <strong>Today</strong> view of the <a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=295405621&amp;mt=8">Surf Report</a> app (see right or <a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=295405621&#038;mt=8">free on AppStore</a>) that was released on the AppStore recently, then the WebKit is just the best thing since the electric bread slicer for speed of development. </p>
<p>Holy grail of iPhone development?</p>
<p>Well, that&#8217;s what we thought. When I <a href="http://drnicwilliams.com/2008/11/04/iphone-dev-podcast-about-fmdb-migration-manager-and-rbiphonetest/">chatted with Dan Grigsby</a> last week I mentioned there were good and bad things about the WebKit within an iPhone app.</p>
<p>This article is about good and bad things. The pros and cons. How we managed the integration of the two code-bases. And the answer to the big question: Would we do it again?</p>
<p>Its probably wonderfully useful stuff to know.</p>
<p><span id="more-330"></span></p>
<h3 id="negatives">Negatives</h3>
<p>So first the downsides. It would be remiss of me to fill you full of unbounded promises of easy non-Objective-C victories in your iPhone dev, and not tone them down with a full bucket of wet reality.</p>
<p><strong>Its slow.</strong> When the WebKit is first loaded into memory, and we try to do this behind the scenes as soon as we get control of our app from the OS, it can take a good few seconds for your WebKit object to be available. You get notified of its readiness for action via the delegate:</p>
<pre>- (void)webViewDidFinishLoad:(UIWebView *)webView</pre>
<p><strong>Its slow.</strong> You&#8217;re running an interpreter (JavaScript runtime) on top of a device with a small CPU and small memory. Go figure.</p>
<p>This reminds me of the fabulous &#8220;two minor drawbacks&#8221; scene from the 80s British sci-fi comedy <a href="http://en.wikipedia.org/wiki/Red_Dwarf">Red Dwarf:</a></p>
<pre>CAT: Why don't we drop the defensive shields?
KRYTEN: A superlative suggestion, sir, with just two minor flaws.
  One, we don't have any defensive shields, and
  two, we don't have any defensive shields. Now I realise that,
  technically speaking, that's only one flaw but I thought
  it was such a big one it was worth mentioning twice.</pre>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/p-JfFYZHZLQ&#038;hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/p-JfFYZHZLQ&#038;hl=en&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>
<p><strong>The JavaScript bridge does not appear to block the main thread.</strong> This is a good/bad thing. You can invoke JavaScript code within the WebKit via your native Objective-C code. </p>
<pre>[webview stringByEvaluatingJavaScriptFromString:@"loadData({some: 'data'})"];</pre>
<p>It seems to return control back to your Objective-C code before it has finished executing, so you may need to poll the JavaScript runtime with `isFinished();` calls if you need to know when its complete.</p>
<p>Annoyingly, the Apple documentation for this method suggests otherwise:</p>
<blockquote><p>JavaScript execution time is limited to 5 seconds for each top-level entry point. If your script executes for more than 5 seconds, Safari stops executing the script. This is likely to occur at a random place in your code, so unintended consequences may result. This limit is imposed because <strong>JavaScript execution may cause the main thread to block, so when scripts are running, the user is not able to interact with the webpage.</strong></p></blockquote>
<p>Quirky.</p>
<p><strong>The JavaScript bridge is one directional.</strong> From Objective-C/UIKit you can invoke JavaScript upon the WebKit and henceforth do wonderful things (as per example above).</p>
<p>From JavaScript you have no native nor nice way to invoke methods on Objective-C objects, like you can in the Cocoa implementation of embedded WebKits. What you can do is use custom HTTP protocols, such as <code>surfreport://</code>, to give the OS a way for the webkit to communicate with your app. </p>
<p>We used this for &#8216;Related Photos&#8217; buttons on some news and athlete&#8217;s pages. When you click a button in the webkit, it attempts to redirect to a <code>surfreport://</code> url. The Objective-C code (your `UIApplicationDelegate`) is notified of this, hides the webkit, and displays the related photos using native UI elements. But we could do anything. Your `UIApplicationDelegate` needs to implement the follow method to receive these requests:</p>
<pre>- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url</pre>
<p>Alternately, you could use JavaScript to invoke this url, possible, via an Ajax call. Haven&#8217;t tried it. Might work. Either way, its a dirty hack, and a very annoying situation given that in Cocoa development there is a beautiful two-way bridge. I want that.</p>
<p><strong>Multiple languages in one project.</strong> Whilst we mainly just wanted to take a static HTML file, and dynamically update various elements with application data (e.g. the surf and weather conditions in the example above), we needed to do that via JavaScript. </p>
<p>We came up with a consistent API <code>loadData(json)</code> for all pages, as discussed below; yet when something displayed incorrectly we now had an extra possible point of failure: JavaScript, Objective-C, and the original web service data source (e.g. the <a href="http://www.surfline.com/" title="Surfline">Surfline</a> data for live updates). </p>
<p>To help isolate issues, we used JavaScript unit testing and a layer of &#8220;fixtures&#8221; or samples of JSON that might be sent from Objective-C to JavaScript. The tests passed against the fixtures; so if a QA error appeared in the app, we first checked the JSON being sent against the fixtures schema to isolate whether it was a JavaScript error or a data format error. It happened sufficiently often that its worth raising here.</p>
<h3 id="webkit_for_rapid_prototyping">WebKit for rapid prototyping</h3>
<p>Nonetheless, the WebKit exists and it is awesome at rendering HTML and CSS, with access to the powerful CSS3 transformations and webkit-specific bonus features.</p>
<p>It is highly likely that your designer can make something beautiful looking in Photoshop and cut it up into HTML + CSS. Comparatively, its highly unlikely they can cut it up into native Objective-C code.</p>
<p>So in the initial phases of application development/prototyping, the WebKit is a sweet option to give the designer on your team direct, immediate access to building the app. If performance is an issue, you later replace it with native UI elements.</p>
<h3 id="code_layout_and_samples">Code layout and samples</h3>
<p>In our Xcode project, the structure we use for including HTML and associated assets into our apps is:</p>
<pre>
Classes/           - normal Objective-C .m/.h files
Html/src           - HTML, CSS, and JavaScript files including libraries like jQuery
Html/test          - JavaScript tests
Html/test/fixtures - expected JSON formats to be sent from Objective-C to loadData methods
</pre>
<p><img class="alignright" src="http://img.skitch.com/20081104-xe4b6xpegf2gx2fkm6cj878wjk.png" alt="html and assets"/></p>
<p>These aren&#8217;t Xcode Groups, rather normal filesystem folders. In the Xcode project, the <code>Html/test</code> files are not included nor bundled with the app. The files in <code>Html/src</code> are included in the &#8220;Copy Bundle Resources&#8221; of the Target (see image) and also linked into the project via a sub-group of &#8220;Resources&#8221;, so they can be easily accessed within the project.</p>
<p>But when I did the HTML/JavaScript development I worked from the command-line and TextMate, and lived entirely inside the <code>Html/</code> folder.</p>
<p>For each static HTML page, such as the &#8216;Today&#8217; view above, there will probably be the following files:</p>
<pre>
Html/src/today.html
Html/src/today.css
Html/src/today.js
Html/src/jquery.min.js
Html/test/unit/today_test.html
</pre>
<p>The WebKit will display <code>today.html</code>, which uses normal <code>&lt;link&gt;</code>/<code>&lt;script&gt;</code> to pull in the <code>.css</code> and <code>.js</code> assets. You can quickly see what the page will look like, even before integration into your app, by loading it into the iPhone Simulator (launch the simulator and drag the file in), or even Safari 3.</p>
<p>We settled on a standard API for the primary call from Objective-C into JavaScript: <code>loadData(json)</code>. Bare-bones, this method starts off looking like:</p>
<pre>// This function is called from Objective-C-land to apply
// the surf information to the HTML template
// +data+ is a hash of key -> value
function loadData(data) {
    $('.data').html('N/A');
    $('img.image_data').removeAttr('src');

    // Assume that any data key can be copied into any HTML element with the same ID
    for (var key in data) {
        var value = data[key];
        var value_exists = fieldExists(value);
        var data_value = value_exists ? value : 'N/A';
        var img_src_value = value_exists ? value : 'unknown';
        $('#' + key).
            filter('.data').html(data_value).end().
            filter('.image_data').attr('src', key + '_' + img_src_value + '.png');
    };
}
</pre>
<p>What it does is take a <code>data</code> hash like <code>{ surf_height_amount: '2-3', surf_height_unit: 'ft' }</code> and HTML like:</p>
<pre>&lt;div id="surf_size">
  &lt;span class="data" id="surf_size_amount">&lt;/span>
  &lt;span class="data" id="surf_size_unit">&lt;/span>
&lt;/div>
</pre>
<p>And the <code>loadData</code> method updates it to:</p>
<pre>&lt;div id="surf_size">
  &lt;span class="data" id="surf_size_amount">2-3&lt;/span>
  &lt;span class="data" id="surf_size_unit">ft&lt;/span>
&lt;/div>
</pre>
<p>So we can build arbitrarily complex HTML templates. By allocating meaningful element IDs (<code>surf_height_amount</code>) and tagging the template elements with <code>class="data"</code> we have a simple mechanism for Objective-C to update the HTML. As the template gets more complex, then so too does the <code>loadData</code> method.</p>
<h3 id="would_we_do_it_again">Would we do it again?</h3>
<p>Yes.</p>
<p>The WebKit isn&#8217;t the holy grail for non-Objective-C developers, but if your grand-poobar level skills are in JavaScript and HTML, and your Objective-C/iPhone skills are still catching up, then its a wonderful prototyping platform. Especially for static, complicated displays of data. Especially if that data includes HTML content from an external feed which needs to be rendered.</p>
<p>For Oakley&#8217;s Surf Report app, Anthony is toying with replacing some of the WebKit usage with native UI elements (normal <code>UITableView</code> with custom <code>UITableViewCell</code>s) so that we can get back those precious seconds and give them to the user as a Christmas present.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2008/11/04/iphone-dev-podcast-about-fmdb-migration-manager-and-rbiphonetest/' rel='bookmark' title='Permanent Link: iPhone dev podcast about fmdb-migration-manager and rbiphonetest'>iPhone dev podcast about fmdb-migration-manager and rbiphonetest</a> <small>Radio is where ugly people go. Podcasts is where ugly,...</small></li><li><a href='http://drnicwilliams.com/2008/07/04/unit-testing-iphone-apps-with-ruby-rbiphonetest/' rel='bookmark' title='Permanent Link: Unit Testing iPhone apps with Ruby: rbiphonetest'>Unit Testing iPhone apps with Ruby: rbiphonetest</a> <small> Everything to love about Ruby: the concise, powerful language;...</small></li><li><a href='http://drnicwilliams.com/2006/09/11/prototype-call-dollar-on-string/' rel='bookmark' title='Permanent Link: Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)'>Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)</a> <small>The Prototype library gives us the $() operation for converting...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2008/11/10/to-webkit-or-not-to-webkit-within-your-iphone-app/feed/</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>iPhone dev podcast about fmdb-migration-manager and rbiphonetest</title>
		<link>http://drnicwilliams.com/2008/11/04/iphone-dev-podcast-about-fmdb-migration-manager-and-rbiphonetest/</link>
		<comments>http://drnicwilliams.com/2008/11/04/iphone-dev-podcast-about-fmdb-migration-manager-and-rbiphonetest/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 23:51:18 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Interviews]]></category>
		<category><![CDATA[Iphone]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[Link]]></category>
		<category><![CDATA[Prototype]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=320</guid>
		<description><![CDATA[Radio is where ugly people go. Podcasts is where ugly, niche people go. It doesn&#8217;t get much uglier and nicher than talking about iPhone dev; and the tale of one desperate man X on a desperate journey Y with his desperate sidekick Z, where: X = Dr Nic Y = iPhone development Z = Ruby [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2008/11/10/to-webkit-or-not-to-webkit-within-your-iphone-app/' rel='bookmark' title='Permanent Link: To WebKit or not to WebKit within your iPhone app?'>To WebKit or not to WebKit within your iPhone app?</a> <small> I know HTML. Its on my CV. Expert level....</small></li><li><a href='http://drnicwilliams.com/2008/07/04/unit-testing-iphone-apps-with-ruby-rbiphonetest/' rel='bookmark' title='Permanent Link: Unit Testing iPhone apps with Ruby: rbiphonetest'>Unit Testing iPhone apps with Ruby: rbiphonetest</a> <small> Everything to love about Ruby: the concise, powerful language;...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Radio is where ugly people go. Podcasts is where ugly, niche people go. It doesn&#8217;t get much uglier and nicher than talking about iPhone dev; and the tale of one desperate man X on a desperate journey Y with his desperate sidekick Z, where:</p>
<ol>
<li>X = Dr Nic</li>
<li>Y = iPhone development</li>
<li>Z = Ruby</li>
</ol>
<p>From the <a href="http://www.mobileorchard.com/iphone-development-podcast-2-dr-nic-williams/">Mobile Orchard news desk</a>:</p>
<p><img height="150" width="113" class="alignleft frame" alt="drnic.png" src="http://www.mobileorchard.com/wp-content/uploads/2008/11/drnic.png"/></p>
<blockquote><p>Dr. Nic talks about his <a href="http://github.com/drnic/fmdb-migration-manager">migration manager</a> for updating SQLite iPhone databases, trying to get Ruby onto an iPhone, using <a href="http://github.com/drnic/rbiphonetest/">Ruby to unit-test Objective-C</a> iPhone code, his company <a href="http://mocra.com">Mocra</a>, and the Mobile Orchard Podcast’s lavish recording studios.</p></blockquote>
<p>Dan Grigsby is the interviewer and post-production guy for the interview, and so it is entirely his handy work that it seems like I&#8217;m the only one talking for 15 minutes. The original interview took 4 hours and it was mostly him talking. He&#8217;s quite a chatterbox. I barely got a word in edgewise. [1]</p>
<p>Dan also created this list of &#8220;things we talked about&#8221;:</p>
<ol>
<li>0:00: Migrations for SQLite</li>
<li>5:18: Getting Ruby onto an iPhone</li>
<li>5:59: Nu &#8211; Lisp-based language that sits atop Obj-C and would work on the iPhone</li>
<li>7:37: Unit testing Obj-C from Ruby</li>
<li>8:12: Webkit UIs</li>
<li>12:31: Mocra / “Used my blog for evil”</li>
</ol>
<p><a href="http://www.mobileorchard.com/iphone-development-podcast-2-dr-nic-williams/"><img alt="" src="http://img.skitch.com/20081103-ft9pt2tfg8pekbj7hu2y8jijb2.png" title="Mobile Orchard" class="alignright" width="354" height="107" /></a><br />
Go to <a href="http://www.mobileorchard.com/iphone-development-podcast-2-dr-nic-williams/">Mobile Orchard</a> (or Mobile Awkward it is accidently called at the end of the interview) to <a href="http://www.mobileorchard.com/iphone-development-podcast-2-dr-nic-williams/">cop a listen</a>.</p>
<p>[1] This paragraph starts well and ends with blatant falsehoods.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2008/11/10/to-webkit-or-not-to-webkit-within-your-iphone-app/' rel='bookmark' title='Permanent Link: To WebKit or not to WebKit within your iPhone app?'>To WebKit or not to WebKit within your iPhone app?</a> <small> I know HTML. Its on my CV. Expert level....</small></li><li><a href='http://drnicwilliams.com/2008/07/04/unit-testing-iphone-apps-with-ruby-rbiphonetest/' rel='bookmark' title='Permanent Link: Unit Testing iPhone apps with Ruby: rbiphonetest'>Unit Testing iPhone apps with Ruby: rbiphonetest</a> <small> Everything to love about Ruby: the concise, powerful language;...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2008/11/04/iphone-dev-podcast-about-fmdb-migration-manager-and-rbiphonetest/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>GitHub Badge for your Blog with 100% guarantee of more coolness</title>
		<link>http://drnicwilliams.com/2008/05/03/github-badge-for-your-blog/</link>
		<comments>http://drnicwilliams.com/2008/05/03/github-badge-for-your-blog/#comments</comments>
		<pubDate>Sat, 03 May 2008 04:14:11 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=272</guid>
		<description><![CDATA[The killer app for JavaScript in the 90s was to take a perfectly readable sequence of words &#8211; aka &#8220;a sentence&#8221; &#8211; and turn every single character a different colour. You did that, then you went back to doing normal work. The killer app for JavaScript in the 00s is widgets/badges. Taking perfectly useful stuff [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2008/12/21/migrating-project-websites-to-github-pages-with-sake-tasks-new-websites-with-jekyll_generator/' rel='bookmark' title='Permanent Link: Migrating project websites to github pages with sake tasks, new websites with jekyll_generator'>Migrating project websites to github pages with sake tasks, new websites with jekyll_generator</a> <small> Its almost Christmas time and that means presents. It...</small></li><li><a href='http://drnicwilliams.com/2008/05/28/how-to-yell-at-people-with-github-from-textmate/' rel='bookmark' title='Permanent Link: How to yell at people with GitHub from TextMate'>How to yell at people with GitHub from TextMate</a> <small>Sometimes when you are perusing code you ask the question:...</small></li><li><a href='http://drnicwilliams.com/2008/05/26/github-and-textmate-unite/' rel='bookmark' title='Permanent Link: GitHub and TextMate Unite'>GitHub and TextMate Unite</a> <small>I wanted to go from a source file to the...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://drnicjavascript.rubyforge.org/github_badge/"><img src="http://img.skitch.com/20080503-jdweqc5md718di54qn8mwjseec.jpg" alt="GitHub Badge" /></a></p>
<p>The killer app for JavaScript in the 90s was to take a perfectly readable sequence of words &#8211; aka &#8220;a sentence&#8221; &#8211; and turn every single character a different colour. You did that, then you went back to doing normal work.</p>
<p>The killer app for JavaScript in the 00s is widgets/badges. Taking perfectly useful stuff from one website &#8211; aka &#8220;data&#8221; &#8211; and re-posting it on your blog sidebar.</p>
<p>In both circumstances, across two decades, you did this to look cool. Sure, it never works but you do it anyway.</p>
<p>Thusly, riding high on the world-dominating success of GitHub there seems to be a vacancy in the department of &#8220;JavaScript badge for my blog to make me look cool&#8221; projects, in the sub-category of &#8220;GitHub&#8221;.</p>
<p>The first entrant and thus market leader of the &#8220;Blog Badges for GitHub&#8221; micro-industry is the &#8220;<a href="http://drnicjavascript.rubyforge.org/github_badge/">GitHub Badge</a>&#8221; It is beautifully demonstrated in static image form above, or if you click the image through to the website (or <a href="http://drnicwilliams.com">here</a> to my blog and its aesthetically appealing enhancement with said GitHub Badge) you&#8217;ll see it live and interactive. </p>
<p>Touch it. Feel it. Press the &#8220;Show more&#8221; link for hours of entertainment.</p>
<h3 id="installation">Installation</h3>
<p>Then get it for yourself. Read the <a href="http://drnicjavascript.rubyforge.org/github_badge/">GitHub Badge</a> website or just&#8230;</p>
<p>Slap the following into your blog sidebar:</p>
<pre>&lt;div id="github-badge"&gt;&lt;/div&gt;
&lt;script type="text/javascript" charset="utf-8"&gt;
  GITHUB_USERNAME="drnic";
  GITHUB_LIST_LENGTH=10;
  GITHUB_HEAD="div"; // e.g. change to "h2" for wordpress sidebars
&lt;/script&gt;
&lt;script src="http://drnicjavascript.rubyforge.org/github_badge/dist/github-badge-launcher.js" type="text/javascript"&gt;&lt;/script&gt;
</pre>
<p>Only GITHUB_USERNAME is a required pre-set variable. The others above show the defaults, and can be changed by being specified.</p>
<p>For my WordPress sidebar, which uses <code>&lt;li&gt;</code> and <code>&lt;h2&gt;</code> for sections and headers, I use the following:</p>
<pre>&lt;li id="github-badge"&gt;&lt;/li&gt;
&lt;script type="text/javascript" charset="utf-8"&gt;
  GITHUB_USERNAME="drnic";
  GITHUB_HEAD="h2";
&lt;/script&gt;
&lt;script src="http://drnicjavascript.rubyforge.org/github_badge/dist/github-badge-launcher.js" type="text/javascript"&gt;&lt;/script&gt;
</pre>
<p>Thus the badge is inserted in the <code>&lt;li&gt;</code> element, and the &#8220;My projects (drnic)&#8221; header is an <code>&lt;h2&gt;</code> instead of a <code>&lt;div&gt;</code>.</p>
<h3 id="source_and_tests_on_github">Source and tests on github</h3>
<p>You can fetch the source from github &#8211; <a href="http://github.com/drnic/github_badges/tree/master">http://github.com/drnic/github_badges/tree/master</a> &#8211; using:</p>
<pre>git clone git://github.com/drnic/github_badges.git
</pre>
<p>You might want to add an option to turn off the auto-CSS generator so you can theme it yourself.</p>
<p>The JavaScript tests are in <code>test/</code> folder. Either run them with <code>rake test</code>, or individually open the files in your browser.</p>
<h3 id="future_cool_things_the_badge_could_do8230">Future cool things the badge could do&#8230;</h3>
<p>Ultimately, when Chris Wanstrath (harass him on <a href="http://twitter.com/defunkt">twitter</a>) adds more fields and APIs to the <a href="http://github.com/guides/the-github-api">GitHub API</a> then the badge can do more. Currently it orders the projects in reverse order &#8211; that is, newest projects first. If I can get the network/watching counters then I can order the list using those values, etc. </p>
<p>Any other cool ideas for what the badge could do?</p>
<p>I&#8217;d like to be able to show project version numbers (e.g. gem version numbers) and other project meta-information. This would require GitHub to offer a CRUD UI for generic key/values and for the fields to be returned via their API.</p>
<p>If you know Chris and can throw heavy objects at him with moderate certainty of hitting him and not damaging any expensive equipment, please do so til he gives me this stuff.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2008/12/21/migrating-project-websites-to-github-pages-with-sake-tasks-new-websites-with-jekyll_generator/' rel='bookmark' title='Permanent Link: Migrating project websites to github pages with sake tasks, new websites with jekyll_generator'>Migrating project websites to github pages with sake tasks, new websites with jekyll_generator</a> <small> Its almost Christmas time and that means presents. It...</small></li><li><a href='http://drnicwilliams.com/2008/05/28/how-to-yell-at-people-with-github-from-textmate/' rel='bookmark' title='Permanent Link: How to yell at people with GitHub from TextMate'>How to yell at people with GitHub from TextMate</a> <small>Sometimes when you are perusing code you ask the question:...</small></li><li><a href='http://drnicwilliams.com/2008/05/26/github-and-textmate-unite/' rel='bookmark' title='Permanent Link: GitHub and TextMate Unite'>GitHub and TextMate Unite</a> <small>I wanted to go from a source file to the...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2008/05/03/github-badge-for-your-blog/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>One-stop JavaScript Unit Testing for Rails 2.0</title>
		<link>http://drnicwilliams.com/2008/02/19/one-stop-javascript-unit-testing-for-rails2/</link>
		<comments>http://drnicwilliams.com/2008/02/19/one-stop-javascript-unit-testing-for-rails2/#comments</comments>
		<pubDate>Tue, 19 Feb 2008 04:08:30 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[newjs]]></category>
		<category><![CDATA[RubiGen]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2008/02/19/one-stop-javascript-unit-testing-for-rails2/</guid>
		<description><![CDATA[Previously, I mentioned a multi-step/multi-project solution to doing JavaScript Unit Testing for Rails, including an autotest script to make TDD life easier for the autotest-addicted. It was too many steps, too many different projects, and too much dependence on prototypejs. So let&#8217;s fix this via the spanky new newjs (introduced here): Instead of several steps, [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2012/04/10/instant-new-rails-applications-with-the-app-scrolls/' rel='bookmark' title='Permanent Link: Instant new Rails applications with the App Scrolls'>Instant new Rails applications with the App Scrolls</a> <small>When I start a new project I want to start...</small></li><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/">Previously</a>, I mentioned a multi-step/multi-project solution to doing JavaScript Unit Testing for Rails, including an autotest script to make TDD life easier for the autotest-addicted.</p>
<p>It was too many steps, too many different projects, and too much dependence on <a href="http://prototypejs.org">prototypejs</a>. So let&#8217;s fix this via the spanky new <a href="http://newjs.rubyforge.org">newjs</a> (<a href="http://drnicwilliams.com/2008/02/17/newjs-javascript-project-generator/">introduced here</a>):</p>
<p>Instead of several steps, there is now two steps:</p>
<pre>
cd myrailsapp                # rails 2.0 app
sudo gem install newjs       # v1.3.1+
script/generate javascript_test application
    create  vendor/plugins/javascript_unittest/lib
    create  vendor/plugins/javascript_unittest/tasks
    create  test/javascript/assets/jsunittest.js
    create  test/javascript/assets/unittest.css
    create  config/javascript_test_autotest.yml.sample
    create  vendor/plugins/javascript_unittest/lib/jstest.rb
    create  vendor/plugins/javascript_unittest/tasks/runner.rake
    create  vendor/plugins/javascript_unittest/tasks/autotest.rake
    create  vendor/plugins/javascript_unittest/README
    create  test/javascript/application_test.html
    create  script/rstakeout
    create  script/js_autotest
</pre>
<p>It installs all assets, gives you a <code>rake test:javascripts</code> task, gives you <code>script/js_autotest</code>, and finally (and most importantly), creates the <code>application_test.html</code> test stub.</p>
<p>As always, you can also run a single test file by loading it into a browser.</p>
<h3 id="prototype_independence">Prototype independence</h3>
<p>Previously, the test suite &#8211; unittest.js &#8211; had a dependency on <a href="http://prototypejs.org">prototypejs</a>. This was wonderful if you&#8217;re developing in prototypejs, but could cause some grief if you weren&#8217;t.</p>
<p><a href="http://newjs.rubyforge.org">newjs</a> now comes packed with an identical test suite &#8211; <a href="http://jsunittest.rubyforge.org">jsunittest</a> &#8211; but it is built without a dependency on prototypejs.</p>
<h3 id="merb_et_al_support">Merb et al support</h3>
<p>I wrote a rails generator because I used Rails. If a merb/other framework (Ruby or non-Ruby) wants a similar generator, just ask. Its pretty simple &#8211; I copy over the <code>rails_generators</code> folder into a <code>merb_generators</code> folder in <code>newjs</code> and change some things based on your frameworks&#8217; structure.</p>
<h3 id="alternate_test_suite_support">Alternate test suite support</h3>
<p>If you like another test suite, and want it included in the generators, this might require some additional effort on your part. It probably has different mechanisms for launching runners etc; whereas I was able to steal the rake tests + support libraries from prototypejs. But, it can be done.</p>
<h3 id="peepcode">Peepcode</h3>
<p>These tools will be discussed in animated detail in the forth coming Peepcode &#8220;JavaScript Unit Testing&#8221;.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2012/04/10/instant-new-rails-applications-with-the-app-scrolls/' rel='bookmark' title='Permanent Link: Instant new Rails applications with the App Scrolls'>Instant new Rails applications with the App Scrolls</a> <small>When I start a new project I want to start...</small></li><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2008/02/19/one-stop-javascript-unit-testing-for-rails2/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>newjs = newgem for JavaScript projects; free TDD suite</title>
		<link>http://drnicwilliams.com/2008/02/17/newjs-javascript-project-generator/</link>
		<comments>http://drnicwilliams.com/2008/02/17/newjs-javascript-project-generator/#comments</comments>
		<pubDate>Sun, 17 Feb 2008 05:06:13 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[RubiGen]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2008/02/17/newjs-javascript-project-generator/</guid>
		<description><![CDATA[Want to start a new JavaScript project for a library or widget/badge for your website? You know you should do TDD but wouldn&#8217;t know how to get started, what support libraries you need and where to get them from? You need tools to deploy your library, your website etc? You&#8217;d like a consistent structure to [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2008/10/31/newgem-100-all-thanks-to-cucumber/' rel='bookmark' title='Permanent Link: newgem 1.0.0 all thanks to Cucumber'>newgem 1.0.0 all thanks to Cucumber</a> <small>The New Gem Generator (newgem) was exciting, moderately revolutionary, and...</small></li><li><a href='http://drnicwilliams.com/2008/02/19/one-stop-javascript-unit-testing-for-rails2/' rel='bookmark' title='Permanent Link: One-stop JavaScript Unit Testing for Rails 2.0'>One-stop JavaScript Unit Testing for Rails 2.0</a> <small>Previously, I mentioned a multi-step/multi-project solution to doing JavaScript Unit...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Want to start a new JavaScript project for a library or widget/badge for your website?</p>
<p>You know you should do TDD but wouldn&#8217;t know how to get started, what support libraries you need and where to get them from? </p>
<p>You need tools to deploy your library, your website etc?</p>
<p>You&#8217;d like a consistent structure to your project so that IDEs could provide support (toggle btw  src/person.js and test/unit/person_test.html) [I haven&#8217;t done this bit yet, I&#8217;m sure I&#8217;ll add it to the <a href="http://github.com/drnic/javascript-unittest-tmbundle/tree/master">JavaScipt Unit testing</a> textmate bundle one day soon].</p>
<p>I couldn&#8217;t find anything helpful like this, so I created <code>newjs</code> &#8211; the <a href="http://newjs.rubyforge.org">JavaScript Project Generator</a>.</p>
<h3 id="why">Why?</h3>
<p>But first, an brief history of everything&#8230;</p>
<p>I fell instantly in love with Rails for a couple reasons:</p>
<ul>
<li><code>rails</code> &amp; <code>script/generate</code> commands &#8211; they teach you what files you need<br />
and where they should go</li>
<li>Ajax support &#8211; the marketing phrase &#8220;its as easy to use Ajax as not to&#8221; took me<br />
away from ASP.NET where the new Ajax.NET library was non-trivial to use; RJS<br />
didn&#8217;t exist at this stage, but Rails&#8217; JavaScript support was still awesome</li>
<li>TextMate &#8211; though I didn&#8217;t get to use it for 18 mths til I bought a Mac</li>
</ul>
<p>Later I fell in love with Ruby, for its meta-programming, syntactical possibilities<br />
and free TDD support within Rails.</p>
<p>Then I fell out of love with JavaScript. Partly because Rails started generating JavaScript for me, and ultimately because I didn&#8217;t have test support. Whether you use Rails JavaScript helpers, or write your own unobtrusive JavaScript libraries you&#8217;re still living in an unhappy world without tests; let alone without TDD.</p>
<p>I still wrote JavaScript because it still needed writing. But a lot of my JavaScript<br />
became &#8220;write-once, modify-never&#8221; affairs. Not just because I had no tests,<br />
but each project had a different structure, different deployment processes, etc.</p>
<p>Finally, this year I figured out &#8220;TDD for JavaScript&#8221;. For every 1000 blog articles about Rails or Ruby, there is 0-1 article on unit testing JavaScript. Or perhaps I just don&#8217;t know how to use Google. Soon, the &#8220;JavaScript Unit Testing&#8221; <a href="http://peepcode.com">PeepCode</a> will be finished, so hopefully it will add to this lacking body of knowledge.</p>
<p>What I needed now was one-line starter-kit for new JavaScript projects that included:</p>
<ul>
<li>A standard structure for JavaScript libraries/projects</li>
<li>In-built testing support, with <code>rake</code> tasks and <code>script/generate unit_test</code><br />
generators</li>
<li>Tasks for deploying distribution files (via version numbers)</li>
<li>Tasks for managing the project website</li>
</ul>
<p>I don&#8217;t think there is one already, thus my hand was forced: <a href="http://newjs.rubyforge.org">newjs</a>.</p>
<h3 id="installation_getting_started">Installation &amp; Getting Started</h3>
<p>Installation and maintenance of generated JavaScript projects requires the installation of <a href="http://www.ruby-lang.org/">Ruby</a> and <a href="http://rubygems.org/">RubyGems</a>.</p>
<p>The command-line application <code>newjs</code> is installed as below, for any operating system (except the &#8216;sudo&#8217; part &#8211; use as necessary):</p>
<pre>sudo gem install newjs</pre>
<p>You&#8217;ll note it uses <a href="http://rubigen.rubyforge.org">RubiGen</a> because I like to cheat when it comes to generating things.</p>
<p>To kick-off your new project/library, run the command-line app <code>newjs</code>:</p>
<pre>$ newjs mylib -a "Dr Nic" -e "drnicwilliams@gmail.com" -u "http://mylib.rubyforge.org"
      create  config
      create  lib
      create  src
      create  script
      create  tasks
      create  test/assets
      create  test/assets/unittest.css
      create  test/assets/unittest.js
      create  test/assets/prototype.js
      create  tasks/javascript_test_autotest_tasks.rake
      create  tasks/environment.rake
      create  tasks/deploy.rake
      create  config/javascript_test_autotest.yml.sample
      create  lib/protodoc.rb
      create  lib/jstest.rb
      create  Rakefile
      create  README.txt
      create  History.txt
      create  License.txt
      create  src/HEADER
      create  src/mylib.js
      create  script/rstakeout
      create  script/js_autotest
  dependency  install_rubigen_scripts
      exists    script
      create    script/generate
      create    script/destroy
</pre>
<p>And you thought you wanted to create all that by hand&#8230;</p>
<h3 id="tdd_for_javascript">TDD for JavaScript</h3>
<p>Personally, I can never remember what basic HTML + JavaScript goes in the test HTML files. I quite like the <a href="http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/">javascript_test plugin</a> for Rails, which allows you to generate a test HTML stub. So I&#8217;ve included a version of it<br />
here.</p>
<p>Two actually: one for unit tests and one for functional tests.</p>
<pre>$ script/generate unit_test some_lib
  create  test/unit
  create  test/unit/some_lib_test.html
</pre>
<p>For functional tests, use <code>functional_test</code> generator. See the <a href="http://newjs.rubyforge.org">newjs site</a> for more details.</p>
<h3 id="lifecycle_of_javascript_files">Lifecycle of JavaScript files</h3>
<p>You create JavaScript files in <code>src/</code> and then when you run <code>rake dist</code><br />
they can compressed into <code>dist/project_name.js</code>. </p>
<p>To make this work, add new <code>src/</code> files into <code>src/project_name.js</code> via<br />
<code>&lt;%= include "file_name.js" %&gt;</code>.</p>
<p>This is the build mechanism used by <a href="http://prototypejs.org" alt="PrototypeJS">prototypejs</a> and I stole it. Actually, I stole nearly everything from the prototypejs source structure.</p>
<h3 id="other_stuff">Other stuff</h3>
<p>Like <a href="http://newgem.rubyforge.org">newgem</a> you can create a simple website (via textile files):</p>
<pre>script/generate install_website
</pre>
<p>BONUS: instead of the crap purple default theme for <code>newgem</code>, <code>newjs</code> websites have a nice yellow theme &#8211; <a href="http://drnicutilities.rubyforge.org/drnic_js_test_helpers/" alt=" Dr Nic’s JavaScript Test Helpers">see example</a>.</p>
<h3 id="source">Source for newjs</h3>
<p>Get it via git: <a href="http://github.com/drnic/newjs/tree/master">master branch</a></p>
<h3 id="credits">Credits</h3>
<p>The generated structure, the unittest.js test suite, and its included help files mostly come from <a href="http://prototypejs.org PrototypeJS">prototypejs</a> and <a href="http://newgem.rubyforge.org">newgem</a>.</p>
<p>The generator mechanism is from <a href="http://rubigen.rubyforge.org">RubiGem</a> which comes from the Rails Generator created by Jeremy &#8220;<a href="http://www.oreillynet.com/ruby/blog/2007/09/7_reasons_i_switched_back_to_p_1.html">I made someone leave Rails for PHP</a>&#8221; Kemper.</p>
<p>Actually, I stole nearly everything from the prototypejs source structure. They are much cleverer than I am.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2008/10/31/newgem-100-all-thanks-to-cucumber/' rel='bookmark' title='Permanent Link: newgem 1.0.0 all thanks to Cucumber'>newgem 1.0.0 all thanks to Cucumber</a> <small>The New Gem Generator (newgem) was exciting, moderately revolutionary, and...</small></li><li><a href='http://drnicwilliams.com/2008/02/19/one-stop-javascript-unit-testing-for-rails2/' rel='bookmark' title='Permanent Link: One-stop JavaScript Unit Testing for Rails 2.0'>One-stop JavaScript Unit Testing for Rails 2.0</a> <small>Previously, I mentioned a multi-step/multi-project solution to doing JavaScript Unit...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2008/02/17/newjs-javascript-project-generator/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Autotesting Javascript in Rails</title>
		<link>http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/</link>
		<comments>http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/#comments</comments>
		<pubDate>Fri, 04 Jan 2008 04:05:45 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Prototype]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/</guid>
		<description><![CDATA[I used to love Javascript so much that it would scare me. Why? Because I used to never write any tests. No unit tests. No integration tests (e.g. Selenium). Why? I didn&#8217;t know how. Not properly. I didn&#8217;t know how to write Javascript unit tests with an autotesting tool, like ZenTest&#8217;s autotest command. And now&#8230; [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2012/04/10/instant-new-rails-applications-with-the-app-scrolls/' rel='bookmark' title='Permanent Link: Instant new Rails applications with the App Scrolls'>Instant new Rails applications with the App Scrolls</a> <small>When I start a new project I want to start...</small></li><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>I used to love Javascript so much that it would scare me. Why? Because I used to never write any tests. No unit tests. No integration tests (e.g. Selenium). Why? I didn&#8217;t know how. Not properly. I didn&#8217;t know how to write Javascript unit tests with an autotesting tool, like ZenTest&#8217;s <code>autotest</code> command.</p>
<p>And now&#8230;</p>
<p><a href='http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/248/' rel='attachment wp-att-248' title='javascript-testing-intro.jpg'><img src='http://drnicwilliams.com/wp-content/uploads/2008/01/javascript-testing-intro.jpg' alt='javascript-testing-intro.jpg' /></a></p>
<p>I am now free to write as much Javascript as I like knowing forever I&#8217;ll write Javascript tests first, and Javascript in libraries second. TDD for Javascript beckons!</p>
<p>Below is a &#8220;getting started&#8221; tutorial, a helpful autotesting plugin, and hints about a TextMate bundle for Javascript Unit Testing and a future <a href="http://peepcode.com">Peepcode</a> on Javascript Unit Testing.</p>
<h2 id="installation">Installation</h2>
<p>Fundamentally, the ideas here are app server-neutral. We&#8217;re using the unittest.js library from scriptaculous. But here I&#8217;ll show/demo the Rails plugins that make this all uber easy to get started.</p>
<p>Firstly, create a blank rails app, or use an existing app. The tutorial should be non-invasive &#8211; just a few &#8220;demo&#8221; files to delete when you&#8217;re done. This tutorial is independent of your app.</p>
<pre>ruby script/plugin install javascript_test
mkdir test/javascript
ln -s ../../vendor/plugins/javascript_test/assets/ test/javascript/assets
</pre>
<p>For Windows people copy vendor/plugins/javascript_test/assets into test/javascript/assets, as you don&#8217;t have symbolic links, which is sad.</p>
<p>At this stage, you can add and commit these files to your project. The rest of this article is destructible demo files and tests.</p>
<h2 id="creating_javascript_tests">Creating javascript tests</h2>
<p>Let&#8217;s say</p>
<pre>$ ruby script/generate javascript_test maths
    exists  test/javascript
    exists  public/javascripts
    create  test/javascript/maths_test.html
    create  public/javascripts/maths.js
</pre>
<p><code>maths.js</code> is just a blank javascript file. The important file is <code>maths_test.html</code>. Its packed with lots of &#8220;getting started&#8221; goodies.</p>
<p>Open <code>test/javascript/maths_test.html</code> and find the <code>testTruth</code> method. </p>
<pre>testTruth: function() { with(this) {
  assert(true);
}}
</pre>
<p>This is an example of a javascript test method, with a sample assert call. It has the same api as the Ruby test::unit assert call. Thomas Fuchs&#8217; presentation <a href="http://mir.aculo.us/2006/09/16/adventures-in-javascript-testing">Adventures in JavaScript testing</a> gives a good rundown of the available assert methods (and the BDD style syntax that is available). I&#8217;m also preparing a TextMate bundle to generate the assert calls, with the same &#8220;as&#8221;, &#8220;ase&#8221;, &#8220;asnn&#8221; tab completions as the Ruby bundle. It makes me happy when using it.</p>
<h2 id="running_unit_tests">Running unit tests</h2>
<p>The most holistic way to run your javascript unittests, is against all the browsers you have on your local machine. The javascript_test plugin comes with a rake task for this: <code>test:javascripts</code></p>
<pre>$ rake test:javascripts
(in /Users/nicwilliams/Documents/rails_apps/imindi_theme)
/test/javascript/maths_test.html on Safari: SUCCESS
/test/javascript/maths_test.html of Firefox: SUCCESS
Skipping Internet Explorer, not supported on this OS
Skipping Konqueror, not supported on this OS
</pre>
<p>In the browsers you&#8217;ll see:</p>
<p><a href='http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/249/' rel='attachment wp-att-249' title='javascript-unit-test-file.jpg'><img src='http://drnicwilliams.com/wp-content/uploads/2008/01/javascript-unit-test-file.jpg' alt='javascript-unit-test-file.jpg' /></a></p>
<p>It runs all your tests on all browsers. That&#8217;s great for a Continuous Integration process, but for me, coming from the ZenTest world of <code>autotest</code>, I only want to run those tests for which something has changed. </p>
<p>I want continual feedback. Small change, run small test. <code>autotest</code> gives me that for Ruby, but <code>rake test:javascript</code> doesn&#8217;t. </p>
<h2 id="autotesting_javascript_tests">Autotesting javascript tests</h2>
<p>On my Mac, I&#8217;ve set up something as a starting point for autotesting javascript tests, based on the &#8220;small change, run small test&#8221; principle.</p>
<pre>$ ruby script/plugin install http://drnicutilities.rubyforge.org/svn/plugins/javascript_test_autotest/
.
.
Edit config/javascript_test_autotest.yml for the browser(s) to use for autotesting.
</pre>
<p>Open config/javascript_test_autotest.yml and uncomment the browser(s) you want to autotest with. I autotest on Safari on the Mac, even though I develop/debug on Firefox, because it reloads each page in the same tab, which I like, and I&#8217;m having problems getting this to work into Firefox at all.</p>
<p>My yml file looks like:</p>
<pre>browsers:
  safari: '/Applications/Safari.app/Contents/MacOS/Safari'
</pre>
<p>So, the current version is known to work for Mac OS X and Safari. If you get this plugin working on different O/S and browsers, let me know below or please submit a patch to <a href="http://groups.google.com/group/drnicutilities">http://groups.google.com/group/drnicutilities</a></p>
<p>From a command line:</p>
<pre>$ script/js_autotest
Watching public/javascripts/controls.js, public/javascripts/application.js, test/javascript/maths_test.html, public/javascripts/effects.js, public/javascripts/dragdrop.js, public/javascripts/prototype.js

Files: 6
</pre>
<h2 id="let8217s_tdd_with_js_autotest">Let&#8217;s TDD with js_autotest</h2>
<p>In <code>test/javascript/maths_test.html</code>, replace <code>testTruth</code>, with the following and save:</p>
<pre>// Maths class should exist
testMathsClassShouldExist: function() { with(this) {
  assert(Maths, 'Where is Maths?');
}},
</pre>
<p><code>js_autotest</code> will automatically load <code>maths_test.html</code> into your browser, and its tests executed.</p>
<p><a href='http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/250/' rel='attachment wp-att-250' title='javascript-testing-failure.jpg'><img src='http://drnicwilliams.com/wp-content/uploads/2008/01/javascript-testing-failure.jpg' alt='javascript-testing-failure.jpg' /></a></p>
<p>Now, let&#8217;s fix the problem by creating the Maths javascript class. In public/javascripts/maths.js, add:</p>
<pre>var Maths = Class.create();
Maths.prototype = {
  initialize: function() {

  }
}
</pre>
<p><code>js_autotest</code> will again automatically reload <code>maths_test.html</code> into your browser, and its tests executed.</p>
<p><a href='http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/251/' rel='attachment wp-att-251' title='javascript-testing-success.jpg'><img src='http://drnicwilliams.com/wp-content/uploads/2008/01/javascript-testing-success.jpg' alt='javascript-testing-success.jpg' /></a></p>
<p>Yay for TDD and Yay for &#8220;small change, run small test&#8221;.</p>
<h2 id="peepcode">Peepcode</h2>
<p>I love Geoffrey&#8217;s <a href="http://peepcode.com">Peepcodes</a>. Geoffrey has all my money in Peepcode credits. More importantly, Geoffrey&#8217;s due to give birth this year to #1 child. Geoffrey, who <a href="http://www.approachingnormal.com/2008/1/2/interview-geoffrey-grosenbach-on-peepcode-entrepreneurship-and-making-book-publishing-easier">works from home</a>, is blissfully unaware that soon he&#8217;ll be a full-time father and part-time Peepcode author. This could mean fewer peepcodes on important peepcode-worthy topics.</p>
<p>I always wished there was a Peepcode on Javascript Unit Testing. It would take many blog posts to cover as much as can be covered in a single 60 minutes peepcode. So, we&#8217;re writing/videoing one. </p>
<p>As a Javascript developer [has anyone ever heard of a Javascript Users Group?] let me know what specifically you&#8217;d like covered in this video, so I don&#8217;t accidently miss something. </p>
<h2 id="optional_install_some_patches"><strike>[optional] Install some patches</strike></h2>
<p>There was a section here about some patches that could be applied. These have now been applied, and javascript_test plugin has been updated with prototype 1.6.0.1. Life is good.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2012/04/10/instant-new-rails-applications-with-the-app-scrolls/' rel='bookmark' title='Permanent Link: Instant new Rails applications with the App Scrolls'>Instant new Rails applications with the App Scrolls</a> <small>When I start a new project I want to start...</small></li><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
	</channel>
</rss>

