diff --git a/spec/javascripts/helpers/SpecHelper.js b/spec/javascripts/helpers/SpecHelper.js
index d6e1fd836968700dedbc59e26e8567f584dfe242..f7aa903333bd35cc8a69fc7264cecfe6bbdabf24 100644
--- a/spec/javascripts/helpers/SpecHelper.js
+++ b/spec/javascripts/helpers/SpecHelper.js
@@ -8,3 +8,79 @@
 //    }
 //  })
 //});
+
+beforeEach(function() {
+  $('#jasmine_content').empty();
+  spec.clearLiveEventBindings();
+  jasmine.Clock.useMock();
+});
+
+afterEach(function() {
+  spec.clearLiveEventBindings();
+  expect(spec.loadFixtureCount).toBeLessThan(2);
+  spec.loadFixtureCount = 0;
+});
+
+var context = describe;
+var spec = {};
+
+spec.clearLiveEventBindings = function() {
+  var events = jQuery.data(document, "events");
+  for (prop in events) {
+    delete events[prop];
+  }
+};
+
+spec.content = function() {
+  return $('#jasmine_content');
+};
+
+// Loads fixure markup into the DOM as a child of the jasmine_content div
+spec.loadFixture = function(fixtureName) {
+  var $destination = $('#jasmine_content');
+
+  // get the markup, inject it into the dom
+  $destination.html(spec.fixtureHtml(fixtureName));
+
+  // keep track of fixture count to fail specs that
+  // call loadFixture() more than once
+  spec.loadFixtureCount++;
+};
+
+// Returns fixture markup as a string. Useful for fixtures that
+// represent the response text of ajax requests.
+spec.readFixture = function(fixtureName) {
+  return spec.fixtureHtml(fixtureName);
+};
+
+spec.fixtureHtml = function(fixtureName) {
+  if (!spec.cachedFixtures[fixtureName]) {
+    spec.cachedFixtures[fixtureName] = spec.retrieveFixture(fixtureName);
+  }
+  return spec.cachedFixtures[fixtureName];
+};
+
+spec.retrieveFixture = function(fixtureName) {
+
+  // construct a path to the fixture, including a cache-busting timestamp
+  var path = '/tmp/js_dom_fixtures/' + fixtureName + ".fixture.html?" + new Date().getTime();
+  var xhr;
+
+  // retrieve the fixture markup via xhr request to jasmine server
+  try {
+    xhr = new jasmine.XmlHttpRequest();
+    xhr.open("GET", path, false);
+    xhr.send(null);
+  } catch(e) {
+    throw new Error("couldn't fetch " + path + ": " + e);
+  }
+  var regExp = new RegExp(/Couldn\\\'t load \/fixture/);
+  if (regExp.test(xhr.responseText)) {
+    throw new Error("Couldn't load fixture with key: '" + fixtureName + "'. No such file: '" + path + "'.");
+  }
+
+  return xhr.responseText;
+};
+
+spec.loadFixtureCount = 0;
+spec.cachedFixtures = {};
\ No newline at end of file
diff --git a/spec/support/fixture_generation.rb b/spec/support/fixture_generation.rb
new file mode 100644
index 0000000000000000000000000000000000000000..57b7c4a1642319076ac61418abbe984db2462987
--- /dev/null
+++ b/spec/support/fixture_generation.rb
@@ -0,0 +1,43 @@
+Rspec::Rails::ControllerExampleGroup.class_eval do
+
+  # Saves the markup to a fixture file using the given name
+  def save_fixture(markup, name)
+    fixture_path = File.join(Rails.root, 'tmp', 'js_dom_fixtures')
+    Dir.mkdir(fixture_path) unless File.exists?(fixture_path)
+
+    fixture_file = File.join(fixture_path, "#{name}.fixture.html")
+    File.open(fixture_file, 'w') do |file|
+      file.puts(markup)
+    end
+  end
+
+  # From the controller spec response body, extracts html identified
+  # by the css selector.
+  def html_for(selector)
+    doc = Nokogiri::HTML(response.body)
+
+    remove_third_party_scripts(doc)
+    content = doc.css(selector).first.to_s
+
+    return convert_body_tag_to_div(content)
+  end
+
+  # Remove scripts such as Google Analytics to avoid running them
+  # when we load into the dom during js specs.
+  def remove_third_party_scripts(doc)
+    scripts = doc.at('#third-party-scripts')
+    scripts.remove if scripts
+  end
+
+  # Many of our css and jQuery selectors rely on a class attribute we
+  # normally embed in the <body>. For example:
+  #
+  # <body class="workspaces show">
+  #
+  # Here we convert the body tag to a div so that we can load it into
+  # the document running js specs without embedding a <body> within a <body>.
+  def convert_body_tag_to_div(markup)
+    return markup.gsub("<body", '<div').gsub("</body>", "</div>")
+  end
+end
+