Fork me on GitHub

Kernow Soul

Ruby, Rails and JavaScript Consultant

Introducing Scupper, the JavaScript Library for Easily Dealing With HTML Snippets in Test Suites

| Comments

I came across a problem today while writing tests in JavaScript. The code I was testing required a snippet of HTML to work with. A user list needed to be reordered depending on their status. No problem I thought, I’ll create div to store an HTML snippet, then before my test I’ll duplicate and copy it into a test div.

1
2
3
4
5
6
7
8
<div id="snippets" style="display:none">
  <ul id="user-list-snippet">
    <li id="user-0">Shaun White<span class='user-0-status'>busy</span></li>
    <li id="user-1">Jeremy Jones<span class='user-1-status'>online</span></li>
    <li id="user-2">Jake Burton<span class='user-2-status'>offline</span></li>
    <li id="user-3">Tara Dakides<span class='user-3-status'>online</span></li>
  </ul>
</div>

And the JavaScript to copy the element:

1
$("#user-list-snippet").clone().removeAttr("id").attr("id", "user-list").appendTo($('#dom_test'));

Of course when working with id’s in HTML they have to be unique so the technique caused some of the other tests in the suite to fail, I needed to find another way to do this. One thing I hate is using jQuery to create more than a few dom elements as it gets complex very quickly and it’s not easy to see if the code is producing the desired HTML at a glance.

After taking a break I came up with a simple solution, the Scupper library was about to be written. I wanted to write snippets in HTML so I kept the snippet used in the first attempt. I then created a library that collected all of the snippets from the dom, storing them internally, before deleting them from the dom. This allowed the dom to be free from conflicting id’s and general pollution. The HTML snippet became:

1
2
3
4
5
6
7
8
9
10
<div id="snippets" style="display:none">
  <div id="user-list-snippet">
    <ul id="user-list">
      <li id="user-0">Shaun White<span class='user-0-status'>busy</span></li>
      <li id="user-1">Jeremy Jones<span class='user-1-status'>online</span></li>
      <li id="user-2">Jake Burton<span class='user-2-status'>offline</span></li>
      <li id="user-3">Tara Dakides<span class='user-3-status'>online</span></li>
    </ul>
  </div>
</div>

The containing div #user-list-snippet gives an element to latch onto in order to grab the contents inside. I created a method that sucks up all snippets inside a dom element and stores them:

1
2
3
4
5
6
7
8
init: function(element_id){
  var element = $('#' + element_id);
  element.children().each(function(i, elm){
    elm = $(elm);
    Scupper.items[elm.attr('id')] = elm.html();
  });
  element.empty();
}

All that was needed is an easy way to pull them out an insert them into the dom:

1
2
3
4
5
6
7
8
9
10
11
insert_into: function(source_id, destination_id){
  return $('#' + destination_id).append(Scupper.retrieve(source_id));
},

retrieve: function(id){
  if(Scupper.items[id] !== undefined){
    return Scupper.items[id];
  }else{
    throw "Requested Scupper element not found with id: " + id;
  }
}

Calling insert_into() grabs the snippet HTML and inserts it into the specified dom element ready for the test to use it.

If you want to use Scupper the source is freely available on github.

Comments