jquery-bdd
Notes from a jQuery session
Structure of session:
- Jump into an example
- Build some new functionality
- Come back and see the major concepts
- Look at what is actually needed to treat javascript as a first-class citizen
- Different testing libraries
Quick why a library in javascript?
- cross-browser abstraction (dynduo circa 1998 was still hard!)
- jQuery, MooTools, Extjs, Prototype, GWT, YUI, Dojo, …
- I want to work with DOM with some UI abstractions – with a little general purpose
- simple HTML traversing, event handling
- also functional, inline style
- I want plugin type architecture
Story plugin demo
- Viewer of StoryQ results
- StoryQ produces XML, this widget gives the XML a pretty viewer
A screenshot and demo
What would your acceptance criteria be? What do you think some of the behaviours of this page are?
Acceptance:
eg should display the PROJECT at the top with the number of tests
Behaviours:
think in terms of themes: data, display, events
The tests … what does the application do?
- run the tests and see the categories
- data loading: xml
- display: traversing xml and creating html
- events: click handlers
Let’s build some new functionality!
Goal: add “Expand All | Contract All | Toggle” functionality to the page
Acceptance:
- The user should be able to expand, collapse or toggle the tree
Specs
Display:
* should show “Expand All | Contract All | Toggle”
Events:
* should show all results when clicking expand all
* should show only top class when clicked contract all
* should toggle between all and one when clicking on toggle
Coding: Add acceptance
Add Display specs
Add Event specs
Return back to completing the Acceptance
Major aspects we covered
HTML traversing
- I want to program akin to how I look at the page
- I may look for: an element, a style, some content or a relationship
- then perform an action
$(‘#mylist’).append(“
Event handling
- I want to look at page and add event at that point
- I want to load data (ie xml or json)
alert(“div clicked”)
})
$(‘div’).bind(‘drag’, function(){
$(this).addClass(‘dragged’)
})
$(‘#results’).load(‘result.html’)
$.get(‘result.xml’, function(xml){
$(“user”, xml).each(function(){
$(“
})
})
Functional style
- almost everything in jQuery are JQuery objects
- that returns an object
- every method can call a jQuery object
- that means you can chain
- plus I want it to be short code
$(‘
.addClass(‘indent’)
.addClass((idx == 4) ? ‘scenario’ : ”)
.text($(this).attr(‘Prefix’) + ‘ ‘ + $(this).attr(‘Text’))
.append($(‘
.click(function(){ $(this).addClass(‘click’)}))
.appendTo(results)
Plugin architecture
- drop in a widget (including my own)
- then combine, extend
- help understand customisation
- basically just work
$(‘#tree’).treeview();
$.ajax({
url: ‘/update’,
data: name,
type: ‘put’,
success: function(xml){
$(‘#flash’).text(“successful update”).addClass(‘success’)
}
})
With power and simplicity … comes responsibility
- the need to follow conventions
– plugins return an array
– plugins accept parameters but have clear defaults
– respect namespace - the need for structure
– test data
– min & pack
– releases - the need to avoid mundane, time consuming tasks
– downloading jquery latest
– download jQuery UI
– building and releasing packages - needs tests
– I use jsspec
Sounds like real software development?
Treat javascript as a first-class citizen
Give your plugin a directory structure:
/src
/css
/images
query.plugin.js
/test
spec_plugin.js
acceptance_plugin.js
specs.html
acceptance.html
/lib
/jsspec
jquery.min.js
jquery-ui.js
/themes
/base
example.html
Rakefile
History.txt
README.txt
Generate your plugin boilerplate code
jQuery Plugin Generator
* gem install jquery-plugin-generator
(function($) {
$.jquery.test = {
VERSION: “0.0.1″,
defaults: {
key: ‘value’
}
};
$.fn.extend({
jquery.test: function(settings) {
settings = $.extend({}, $.jquery.test.defaults, settings);
return this.each( function(){
self = this;
// your plugin
})
}
})
})(jQuery);
Use a build tool to do the … ah … building
rake acceptance # Run acceptance test in browser
rake bundles:tm # Install TextMate bundles from SVN for jQuery and…
rake clean # Remove any temporary products.
rake clobber # Remove any generated file.
rake clobber_compile # Remove compile products
rake clobber_package # Remove package products
rake compile # Build all the packages
rake example # Show example
rake first_time # First time run to demonstrate that pages are wor…
rake jquery:add # Add latest jquery core, ui and themes to lib
rake jquery:add_core # Add latest jQuery to library
rake jquery:add_themes # Add all themes to libary
rake jquery:add_ui # Add latest jQueryUI (without theme) to library
rake jquery:add_version # Add specific version of jQuery library: see with…
rake jquery:packages # List all packages for core and ui
rake jquery:packages_core # List versions of released packages
rake jquery:packages_ui # List versions of released packages
rake jquery:versions # List all versions for core and ui
rake jquery:versions_core # List jQuery packages available
rake jquery:versions_ui # List jQuery UI packages available
rake merge # Merge js files into one
rake pack # Compress js files to min
rake package # Build all the packages
rake recompile # Force a rebuild of the package files
rake repackage # Force a rebuild of the package files
rake show # Show all browser examples and tests
rake specs # Run spec tests in browser
Testing … acceptance and specs
- specs: BDD style – DOM traversing and events
- acceptance: tasks on the GUI with the packaged version (minified or packed)
- these both server as good documentation as well
- plus, you have demo page baked in!
Compiling and packaging
- Compiling javascript … hhh? … yes, if you minify or pack your code
- gzip compression with caching and header control is probably easier though
- packed code is HARD to debug if it doesn’t work
Now you are ready for some development
Different ways to test Javascript
Understanding JavaScript Testing
- testing for cross-browser issues – so this is useful if you are building javascript frameworks
- Unit – QUnit, JsUnit, FireUnit,
- Behvaiour – Screw.Unit, JSSpec, YUITest,
- Functional with browser launching – Selenium (IDE & RC & HQ), Watir/n, JSTestDriver, WebDriver
- Server-side: Crosscheck, env.js, blueridge
- Distributed: Selenium Grid, TestSwarm
Reference
- slide 48: great explanation of DOM manipulation – append, prepend, after, bfore, wrap, replace …