Skip to content
Browse files

Added ability to submit an email address to receive updates.

This includes:
* ajax call on pressing enter in input field 
* jasmine javascript tests for supporting object
* poltergeist based capybara javascript request specs
  • Loading branch information...
1 parent 792ab24 commit adf08eda3cc8178db91db1012b79d5e337e0894d @shageman committed
View
4 Gemfile
@@ -10,6 +10,8 @@ group :test, :development do
gem "capybara"
gem "sqlite3"
- #Development requirements of teaser engine
+ #Development requirements of teaser engine (for travis-ci)
gem "shoulda-matchers"
+ gem "poltergeist"
+ gem "jasmine"
end
View
18 Gemfile.lock
@@ -51,6 +51,9 @@ GEM
ffi (~> 1.0, >= 1.0.6)
diff-lcs (1.1.3)
erubis (2.7.0)
+ eventmachine (1.0.0)
+ faye-websocket (0.4.6)
+ eventmachine (>= 0.12.0)
ffi (1.1.5)
haml (3.1.7)
haml-rails (0.3.5)
@@ -59,7 +62,14 @@ GEM
haml (~> 3.1)
railties (>= 3.1, < 4.1)
hike (1.2.1)
+ http_parser.rb (0.5.3)
i18n (0.6.1)
+ jasmine (1.2.1)
+ jasmine-core (>= 1.2.0)
+ rack (~> 1.0)
+ rspec (>= 1.3.1)
+ selenium-webdriver (>= 0.1.3)
+ jasmine-core (1.2.0)
journey (1.0.4)
jquery-rails (2.1.2)
railties (>= 3.1.0, < 5.0)
@@ -74,6 +84,12 @@ GEM
mime-types (1.19)
multi_json (1.3.6)
nokogiri (1.5.5)
+ poltergeist (0.7.0)
+ capybara (~> 1.1)
+ childprocess (~> 0.3)
+ faye-websocket (~> 0.4, >= 0.4.4)
+ http_parser.rb (~> 0.5.3)
+ multi_json (~> 1.0)
polyglot (0.3.3)
rack (1.4.1)
rack-cache (1.2)
@@ -145,6 +161,8 @@ PLATFORMS
DEPENDENCIES
capybara
+ jasmine
+ poltergeist
rails
rspec-rails
shoulda-matchers
View
6 build.sh
@@ -1,12 +1,18 @@
#!/bin/sh
echo "*** Running container app specs"
source ~/.rvm/scripts/rvm
+bundle install > /dev/null
bundle exec rake db:migrate db:test:prepare rspec
result=$?
echo "*** Running teaser engine specs"
cd engines/teaser
+bundle install > /dev/null
bundle exec rake db:migrate app:db:test:prepare rspec
result+=$?
+echo "*** Running teaser engine javascript specs"
+bundle exec rake app:jasmine:ci
+result+=$?
+
exit $result
View
6 engines/teaser/Gemfile
@@ -2,6 +2,8 @@ source "http://rubygems.org"
gemspec
gem "rspec-rails"
+gem "capybara"
gem "shoulda-matchers"
-
-gem "sqlite3"
+gem "sqlite3"
+gem "poltergeist"
+gem "jasmine"
View
41 engines/teaser/Gemfile.lock
@@ -37,10 +37,24 @@ GEM
activesupport (3.2.8)
i18n (~> 0.6)
multi_json (~> 1.0)
+ addressable (2.3.2)
arel (3.0.2)
builder (3.0.3)
+ capybara (1.1.2)
+ mime-types (>= 1.16)
+ nokogiri (>= 1.3.3)
+ rack (>= 1.0.0)
+ rack-test (>= 0.5.4)
+ selenium-webdriver (~> 2.0)
+ xpath (~> 0.1.4)
+ childprocess (0.3.5)
+ ffi (~> 1.0, >= 1.0.6)
diff-lcs (1.1.3)
erubis (2.7.0)
+ eventmachine (1.0.0)
+ faye-websocket (0.4.6)
+ eventmachine (>= 0.12.0)
+ ffi (1.1.5)
haml (3.1.7)
haml-rails (0.3.5)
actionpack (>= 3.1, < 4.1)
@@ -48,18 +62,34 @@ GEM
haml (~> 3.1)
railties (>= 3.1, < 4.1)
hike (1.2.1)
+ http_parser.rb (0.5.3)
i18n (0.6.1)
+ jasmine (1.2.1)
+ jasmine-core (>= 1.2.0)
+ rack (~> 1.0)
+ rspec (>= 1.3.1)
+ selenium-webdriver (>= 0.1.3)
+ jasmine-core (1.2.0)
journey (1.0.4)
jquery-rails (2.1.2)
railties (>= 3.1.0, < 5.0)
thor (~> 0.14)
json (1.7.5)
+ libwebsocket (0.1.5)
+ addressable
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.19)
multi_json (1.3.6)
+ nokogiri (1.5.5)
+ poltergeist (0.7.0)
+ capybara (~> 1.1)
+ childprocess (~> 0.3)
+ faye-websocket (~> 0.4, >= 0.4.4)
+ http_parser.rb (~> 0.5.3)
+ multi_json (~> 1.0)
polyglot (0.3.3)
rack (1.4.1)
rack-cache (1.2)
@@ -99,11 +129,17 @@ GEM
activesupport (>= 3.0)
railties (>= 3.0)
rspec (~> 2.11.0)
+ rubyzip (0.9.9)
sass (3.2.1)
sass-rails (3.2.5)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
+ selenium-webdriver (2.25.0)
+ childprocess (>= 0.2.5)
+ libwebsocket (~> 0.1.3)
+ multi_json (~> 1.0)
+ rubyzip
shoulda-matchers (1.3.0)
activesupport (>= 3.0.0)
sprockets (2.1.3)
@@ -117,11 +153,16 @@ GEM
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.33)
+ xpath (0.1.4)
+ nokogiri (~> 1.3)
PLATFORMS
ruby
DEPENDENCIES
+ capybara
+ jasmine
+ poltergeist
rspec-rails
shoulda-matchers
sqlite3
View
4 engines/teaser/app/assets/javascripts/teaser/application.js
@@ -12,4 +12,8 @@
//
//= require jquery
//= require jquery_ujs
+//= require ./teaser
//= require_tree .
+//= require_self
+
+(new Teaser.SignUp).initialize('#signup', '#results', window.createTeaserUrl);
View
34 engines/teaser/app/assets/javascripts/teaser/signUp.js
@@ -0,0 +1,34 @@
+Teaser.SignUp = function () {
+}
+
+Teaser.SignUp.prototype.initialize = function (inputSelector, resultSelector, signUpEndpoint) {
+ this.signUpEndpoint = signUpEndpoint;
+ this.$inputElement = $(inputSelector);
+ this.$resultElement = $(resultSelector);
+ this.$inputElement.on("keydown", $.proxy(this.signUpIfSubmitted, this));
+}
+
+Teaser.SignUp.prototype.signUp = function () {
+ var that = this;
+ $.post(this.signUpEndpoint, { new_sign_up_entry:this.$inputElement.val() }, function (data) {
+ })
+ .success(function (result) {
+ $.proxy(that.handleSubmissionResult("success", result), that)
+ })
+ .error(function (result) {
+ $.proxy(that.handleSubmissionResult("error", result), that)
+ });
+}
+
+Teaser.SignUp.prototype.signUpIfSubmitted = function (e) {
+ var key = (e.keyCode ? e.keyCode : e.which);
+ if (key == 13) {
+ e.preventDefault();
+ $.proxy(this.signUp(), this);
+ }
+}
+
+Teaser.SignUp.prototype.handleSubmissionResult = function (result, data) {
+ var responseText = data.responseText || data;
+ this.$resultElement.prepend("<p class='" + result + "'>" + responseText + "</p>");
+}
View
1 engines/teaser/app/assets/javascripts/teaser/teaser.js
@@ -0,0 +1 @@
+Teaser = {}
View
16 engines/teaser/app/controllers/teaser/tease_controller.rb
@@ -1,6 +1,20 @@
module Teaser
class TeaseController < Teaser::ApplicationController
- def index
+ def new
+ end
+
+ def create
+ email = params[:new_sign_up_entry].presence
+ render text: "Hey! Please call this right... I need a new signUp entry!", status: 400 and return unless email
+
+ similar_exisiting_entry = Teaser::Entry.find_by_email(email)
+ render text: "Hm... something went wrong. Did you already sign up?", status: 400 and return if similar_exisiting_entry
+
+ if Teaser::Entry.create(email: email)
+ render text: "Thanks for signing up!", status: 200
+ else
+ render text: "Hm... something went seriously wrong.", status: 500
+ end
end
end
end
View
1 engines/teaser/app/models/teaser/entry.rb
@@ -1,5 +1,6 @@
module Teaser
class Entry < ActiveRecord::Base
+ attr_accessible :email
validates :email, presence: true
end
end
View
2 engines/teaser/app/views/layouts/teaser/application.html.erb
@@ -3,7 +3,6 @@
<head>
<title>Teaser</title>
<%= stylesheet_link_tag "teaser/application", :media => "all" %>
- <%= javascript_include_tag "teaser/application" %>
<%= csrf_meta_tags %>
</head>
<body>
@@ -25,4 +24,5 @@
<%= content_for :footer %>
</div>
</body>
+<%= javascript_include_tag "teaser/application" %>
</html>
View
7 ...er/app/views/teaser/tease/index.html.haml → ...aser/app/views/teaser/tease/new.html.haml
@@ -6,4 +6,9 @@
%p Also: sign up to receive our updates
%form
- %input
+ %input#signup
+
+#results
+
+:javascript
+ window.createTeaserUrl = "#{tease_index_url}";
View
3 engines/teaser/config/routes.rb
@@ -1,3 +1,4 @@
Teaser::Engine.routes.draw do
- root :to => 'tease#index'
+ resources "tease", only: [:new, :create]
+ root :to => 'tease#new'
end
View
1 engines/teaser/lib/teaser.rb
@@ -1,6 +1,7 @@
require "teaser/engine"
require "rails/all"
require "haml"
+require "jquery-rails"
require File.expand_path("../monkey_patches/engine.rb", __FILE__)
View
40 engines/teaser/spec/controllers/tease_controller_spec.rb
@@ -2,12 +2,48 @@
module Teaser
describe TeaseController do
- describe "GET index" do
+ describe "GET new" do
it "should not fail" do
expect {
- get :index, use_route: "teaser"
+ get :new, use_route: "teaser"
}.to_not raise_exception
end
end
+
+ describe "POST create" do
+ it "should fail if no new_sign_up_entry parameter is given" do
+ xhr :post, :create, use_route: "teaser"
+ response.status.should == 400
+ response.body.should == "Hey! Please call this right... I need a new signUp entry!"
+
+ xhr :post, :create, new_sign_up_entry: nil, use_route: "teaser"
+ response.status.should == 400
+ response.body.should == "Hey! Please call this right... I need a new signUp entry!"
+ end
+
+ it "should fail if the value given in the new_sign_up_entry parameter already exists in the database" do
+ Teaser::Entry.create!(email: "adam")
+
+ xhr :post, :create, new_sign_up_entry: "adam", use_route: "teaser"
+ response.status.should == 400
+ response.body.should == "Hm... something went wrong. Did you already sign up?"
+ end
+
+ it "should fail if the new entry cannot be saved" do
+ Teaser::Entry.stub(:create).and_return(false)
+
+ xhr :post, :create, new_sign_up_entry: "something unsaveable", use_route: "teaser"
+ response.status.should == 500
+ response.body.should == "Hm... something went seriously wrong."
+ end
+
+ it "should be a success if the new entry can be saved" do
+ Teaser::Entry.stub(:create).and_return(true)
+
+ xhr :post, :create, new_sign_up_entry: "something unsaveable", use_route: "teaser"
+ response.status.should == 200
+ response.body.should == "Thanks for signing up!"
+ end
+ end
end
end
View
207 engines/teaser/spec/javascripts/helpers/mock-ajax.js
@@ -0,0 +1,207 @@
+/*
+ Jasmine-Ajax : a set of helpers for testing AJAX requests under the Jasmine
+ BDD framework for JavaScript.
+
+ Supports both Prototype.js and jQuery.
+
+ http://github.com/pivotal/jasmine-ajax
+
+ Jasmine Home page: http://pivotal.github.com/jasmine
+
+ Copyright (c) 2008-2010 Pivotal Labs
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ */
+
+// Jasmine-Ajax interface
+var ajaxRequests = [];
+
+function mostRecentAjaxRequest() {
+ if (ajaxRequests.length > 0) {
+ return ajaxRequests[ajaxRequests.length - 1];
+ } else {
+ return null;
+ }
+}
+
+function clearAjaxRequests() {
+ ajaxRequests = [];
+}
+
+// Fake XHR for mocking Ajax Requests & Responses
+function FakeXMLHttpRequest() {
+ var extend = Object.extend || $.extend;
+ extend(this, {
+ requestHeaders: {},
+
+ open: function() {
+ this.method = arguments[0];
+ this.url = arguments[1];
+ this.readyState = 1;
+ },
+
+ setRequestHeader: function(header, value) {
+ this.requestHeaders[header] = value;
+ },
+
+ abort: function() {
+ this.readyState = 0;
+ },
+
+ readyState: 0,
+
+ onreadystatechange: function(isTimeout) {
+ },
+
+ status: null,
+
+ send: function(data) {
+ this.params = data;
+ this.readyState = 2;
+ },
+
+ getResponseHeader: function(name) {
+ return this.responseHeaders[name];
+ },
+
+ getAllResponseHeaders: function() {
+ var responseHeaders = [];
+ for (var i in this.responseHeaders) {
+ if (this.responseHeaders.hasOwnProperty(i)) {
+ responseHeaders.push(i + ': ' + this.responseHeaders[i]);
+ }
+ }
+ return responseHeaders.join('\r\n');
+ },
+
+ responseText: null,
+
+ response: function(response) {
+ this.status = response.status;
+ this.responseText = response.responseText || "";
+ this.readyState = 4;
+ this.responseHeaders = response.responseHeaders ||
+ {"Content-type": response.contentType || "application/json" };
+ // uncomment for jquery 1.3.x support
+ // jasmine.Clock.tick(20);
+
+ this.onreadystatechange();
+ },
+ responseTimeout: function() {
+ this.readyState = 4;
+ jasmine.Clock.tick(jQuery.ajaxSettings.timeout || 30000);
+ this.onreadystatechange('timeout');
+ }
+ });
+
+ return this;
+}
+
+
+jasmine.Ajax = {
+
+ isInstalled: function() {
+ return jasmine.Ajax.installed == true;
+ },
+
+ assertInstalled: function() {
+ if (!jasmine.Ajax.isInstalled()) {
+ throw new Error("Mock ajax is not installed, use jasmine.Ajax.useMock()")
+ }
+ },
+
+ useMock: function() {
+ if (!jasmine.Ajax.isInstalled()) {
+ var spec = jasmine.getEnv().currentSpec;
+ spec.after(jasmine.Ajax.uninstallMock);
+
+ jasmine.Ajax.installMock();
+ }
+ },
+
+ installMock: function() {
+ if (typeof jQuery != 'undefined') {
+ jasmine.Ajax.installJquery();
+ } else if (typeof Prototype != 'undefined') {
+ jasmine.Ajax.installPrototype();
+ } else {
+ throw new Error("jasmine.Ajax currently only supports jQuery and Prototype");
+ }
+ jasmine.Ajax.installed = true;
+ },
+
+ installJquery: function() {
+ jasmine.Ajax.mode = 'jQuery';
+ jasmine.Ajax.real = jQuery.ajaxSettings.xhr;
+ jQuery.ajaxSettings.xhr = jasmine.Ajax.jQueryMock;
+
+ },
+
+ installPrototype: function() {
+ jasmine.Ajax.mode = 'Prototype';
+ jasmine.Ajax.real = Ajax.getTransport;
+
+ Ajax.getTransport = jasmine.Ajax.prototypeMock;
+ },
+
+ uninstallMock: function() {
+ jasmine.Ajax.assertInstalled();
+ if (jasmine.Ajax.mode == 'jQuery') {
+ jQuery.ajaxSettings.xhr = jasmine.Ajax.real;
+ } else if (jasmine.Ajax.mode == 'Prototype') {
+ Ajax.getTransport = jasmine.Ajax.real;
+ }
+ jasmine.Ajax.reset();
+ },
+
+ reset: function() {
+ jasmine.Ajax.installed = false;
+ jasmine.Ajax.mode = null;
+ jasmine.Ajax.real = null;
+ },
+
+ jQueryMock: function() {
+ var newXhr = new FakeXMLHttpRequest();
+ ajaxRequests.push(newXhr);
+ return newXhr;
+ },
+
+ prototypeMock: function() {
+ return new FakeXMLHttpRequest();
+ },
+
+ installed: false,
+ mode: null
+}
+
+
+// Jasmine-Ajax Glue code for Prototype.js
+if (typeof Prototype != 'undefined' && Ajax && Ajax.Request) {
+ Ajax.Request.prototype.originalRequest = Ajax.Request.prototype.request;
+ Ajax.Request.prototype.request = function(url) {
+ this.originalRequest(url);
+ ajaxRequests.push(this);
+ };
+
+ Ajax.Request.prototype.response = function(responseOptions) {
+ return this.transport.response(responseOptions);
+ };
+}
View
77 engines/teaser/spec/javascripts/support/jasmine.yml
@@ -0,0 +1,77 @@
+# src_files
+#
+# Return an array of filepaths relative to src_dir to include before jasmine specs.
+# Default: []
+#
+# EXAMPLE:
+#
+# src_files:
+# - lib/source1.js
+# - lib/source2.js
+# - dist/**/*.js
+#
+src_files:
+ - assets/teaser/application.js
+
+# stylesheets
+#
+# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
+# Default: []
+#
+# EXAMPLE:
+#
+# stylesheets:
+# - css/style.css
+# - stylesheets/*.css
+#
+stylesheets:
+ - stylesheets/teaster/**/*.css
+
+# helpers
+#
+# Return an array of filepaths relative to spec_dir to include before jasmine specs.
+# Default: ["helpers/**/*.js"]
+#
+# EXAMPLE:
+#
+# helpers:
+# - helpers/**/*.js
+#
+helpers:
+ - helpers/**/*.js
+
+# spec_files
+#
+# Return an array of filepaths relative to spec_dir to include.
+# Default: ["**/*[sS]pec.js"]
+#
+# EXAMPLE:
+#
+# spec_files:
+# - **/*[sS]pec.js
+#
+spec_files:
+ - '**/*[sS]pec.js'
+
+# src_dir
+#
+# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
+# Default: project root
+#
+# EXAMPLE:
+#
+# src_dir: public
+#
+src_dir:
+ - sources/**/*.js
+
+# spec_dir
+#
+# Spec directory path. Your spec_files must be returned relative to this path.
+# Default: spec/javascripts
+#
+# EXAMPLE:
+#
+# spec_dir: spec/javascripts
+#
+spec_dir: spec/javascripts
View
130 engines/teaser/spec/javascripts/teaser/signup_spec.js
@@ -0,0 +1,130 @@
+describe("Teaser.SignUp", function () {
+ describe("#initialize", function () {
+ it("should transform the given parameters into variables on the object", function () {
+ $("#jasmine_content").html("<p class='input'>within p</p><div class='result'>within div</div>");
+ var signUp = new Teaser.SignUp;
+ signUp.initialize(".input", ".result", "signUpEndpoint");
+
+ expect(signUp.signUpEndpoint).toEqual("signUpEndpoint");
+ expect(signUp.$inputElement.html()).toEqual("within p");
+ expect(signUp.$resultElement.html()).toEqual("within div");
+ });
+
+ it("should register signUpIfSubmitted on keydowns in the input", function () {
+ var signUpIfSubmitted = spyOn(Teaser.SignUp.prototype, "signUpIfSubmitted");
+
+ $("#jasmine_content").html("<p class='input'>within p</p><div class='result'>within div</div>");
+ var signUp = new Teaser.SignUp;
+ signUp.initialize(".input", ".result", "signUpEndpoint");
+
+ $(".input").trigger("keydown")
+
+ expect(signUpIfSubmitted).toHaveBeenCalled();
+ });
+ });
+
+ describe("#signUp", function () {
+ var handleSubmissionResult, request;
+ var callAjax = function () {
+ jasmine.Ajax.useMock();
+
+ handleSubmissionResult = spyOn(Teaser.SignUp.prototype, "handleSubmissionResult");
+
+ var signUp = new Teaser.SignUp;
+ signUp.signUpEndpoint = "signUpEndpoint";
+ signUp.$inputElement = {val:function () {
+ return "value of input"
+ }}
+
+ signUp.signUp();
+
+ request = mostRecentAjaxRequest();
+ }
+
+ it("should post the value of the input element to the signUpEndpoint", function () {
+ var post = spyOn($, "post").andCallThrough()
+
+ callAjax();
+
+ expect(post).toHaveBeenCalledWith("signUpEndpoint", { new_sign_up_entry:"value of input" }, jasmine.any(Function));
+ });
+
+ it("should call handleSubmissionResult with success if the ajax call is successful", function () {
+ callAjax();
+ request.response({status:200, responseText:"{}"});
+
+ expect(handleSubmissionResult).toHaveBeenCalledWith("success", {});
+ });
+
+ it("should call handleSubmissionResult with error if the ajax call is unsuccessful", function () {
+ callAjax();
+ request.response({status:400, responseText:""});
+
+ expect(handleSubmissionResult).toHaveBeenCalledWith("error", jasmine.any(Object));
+ });
+ });
+
+ describe("#signUpIfSubmitted", function () {
+ var signUp, event;
+ beforeEach(function () {
+ signUp = new Teaser.SignUp;
+ spyOn(signUp, "signUp");
+
+ event = jQuery.Event("keydown");
+ });
+
+ describe("when the key pressed is Enter", function () {
+ beforeEach(function () {
+ event.keyCode = 13;
+ });
+
+ it("should prevent default", function () {
+ spyOn(event, "preventDefault");
+ signUp.signUpIfSubmitted(event);
+ expect(event.preventDefault).toHaveBeenCalled();
+ });
+
+ it("should call signUp", function () {
+ signUp.signUpIfSubmitted(event);
+ expect(signUp.signUp).toHaveBeenCalled();
+ });
+ });
+
+ describe("when the key pressed is not Enter", function () {
+ beforeEach(function () {
+ event.keyCode = 14;
+ });
+
+ it("should not prevent default", function () {
+ spyOn(event, "preventDefault");
+ signUp.signUpIfSubmitted(event);
+ expect(event.preventDefault).not.toHaveBeenCalled();
+ });
+
+ it("should not call signUp", function () {
+ signUp.signUpIfSubmitted(event);
+ expect(signUp.signUp).not.toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe("handleSubmissionResult", function () {
+ var signUp;
+
+ beforeEach(function () {
+ $("#jasmine_content").html("<div class='result'></div>");
+ signUp = new Teaser.SignUp;
+ signUp.$resultElement = $(".result");
+ });
+
+ it("should prepend the result's responseText to the $resultElement", function () {
+ signUp.handleSubmissionResult("success_class", {responseText: "this was a success"});
+ expect(signUp.$resultElement.html()).toEqual('<p class="success_class">this was a success</p>');
+ });
+
+ it("should prepend the result to the $resultElement (if there is no responseText)", function () {
+ signUp.handleSubmissionResult("success_class", "this was also a success");
+ expect(signUp.$resultElement.html()).toEqual('<p class="success_class">this was also a success</p>');
+ });
+ });
+});
View
23 engines/teaser/spec/requests/signing_up_for_updates_spec.rb
@@ -0,0 +1,23 @@
+require "spec_helper"
+
+feature "Signing up for tnbt updates", %q{
+ In order to stay informed about the next big thing
+ As a person
+ I want to be able to sign up to updates
+} do
+
+ background do
+ Teaser::Entry.delete_all
+ end
+
+ scenario "sign up", js: "true" do
+ visit "/teaser"
+
+ expect {
+ fill_in "signup", with: "stephan@pivotallabs.com"
+ press_key_on_selector(13, "#signup")
+
+ page.should have_content "Thanks for signing up!"
+ }.to change(Teaser::Entry, :count).from(0).to(1)
+ end
+end
View
7 engines/teaser/spec/spec_helper.rb
@@ -3,12 +3,17 @@
require File.expand_path("../dummy/config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
+require 'capybara/rspec'
-Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
+require 'capybara/poltergeist'
+Capybara.javascript_driver = :poltergeist
+
+Dir[Teaser::Engine.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
#config.fixture_path = "#{::Rails.root}/spec/fixtures"
#config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
+ config.include RequestSpecHelpers
end
View
5 engines/teaser/spec/support/request_spec_helpers.rb
@@ -0,0 +1,5 @@
+module RequestSpecHelpers
+ def press_key_on_selector(key, selector)
+ page.driver.execute_script("var e = $.Event('keydown', { keyCode: #{key} }); $('#{selector}').trigger(e);")
+ end
+end

0 comments on commit adf08ed

Please sign in to comment.
Something went wrong with that request. Please try again.