Permalink
Browse files

Started adding acceptance spec coverage for web app

  • Loading branch information...
1 parent 15adf55 commit 2f64a24a476a16d7d134dffb9d009f7067d9bafc @ddemaree committed Nov 6, 2011
Showing with 174 additions and 33 deletions.
  1. +0 −1 Rakefile
  2. +25 −7 assets/stylesheets/thirty_one.css.scss.erb
  3. +49 −17 spec/app_spec.rb
  4. +11 −0 spec/spec_helper.rb
  5. +28 −5 thirty_one.rb
  6. +23 −3 views/index.erb
  7. +38 −0 views/list_parties.erb
View
@@ -33,7 +33,6 @@ end
namespace :db do
desc "Migrate the database"
task :migrate => [:environment] do
- #ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Migration.verbose = true
ActiveRecord::Migrator.migrate( File.expand_path("../db/migrate", __FILE__) )
end
@@ -103,7 +103,7 @@ label, input, select, textarea {
margin: 0 auto;
font-size: 27px;
line-height: 1.11em;
-
+
@media screen and (min-width:768px){
font-size: 36px;
line-height: 1.11em;
@@ -187,7 +187,7 @@ label, input, select, textarea {
@media screen and (min-width: 940px){
width: percentage(280/940);
}
-
+
h2 {
font-family: $sans-serif-fonts;
font-size: 24px;
@@ -316,12 +316,30 @@ label, input, select, textarea {
width: 220px;
}
}
- #party-guests {
- margin-top: 20px;
+ .field {
label {
+ color: #666;
display: block;
font-size: 17px;
- margin-bottom: 6px;
+ line-height: 1.11em;
+ padding-bottom: 5px;
+ }
+ label,
+ .help-block {
+ @media screen and (min-width:768px){
+ padding-left: 7px;
+ }
+ }
+ }
+ #party-guests {
+ margin-top: 20px;
+
+ @media screen and (min-width:768px){
+ padding-left: 8px;
+ }
+
+ label {
+ padding-left: 0;
line-height: 1.11em;
@media screen and (min-width:940px){
display: inline;
@@ -562,7 +580,7 @@ label, input, select, textarea {
font-family: $serif-fonts;
font-size: 15px;
line-height: 20px;
-
+
@media screen and (min-width:640px){
font-size: 17px;
line-height: 22px;
@@ -597,7 +615,7 @@ label, input, select, textarea {
font-size: 20px;
line-height: 22px;
margin: 15px 0;
-
+
@media screen and (min-width:640px){
font-size: 24px;
line-height: 26px;
View
@@ -1,31 +1,63 @@
require 'spec_helper'
require 'capybara/rspec'
-describe "The web app" do
- include Rack::Test::Methods
+Capybara.app = ThirtyOne::App
- let(:app) { ThirtyOne::App }
-
- describe 'on GET /' do
- it 'renders the form' do
- get '/'
- last_response.should be_ok
- end
+feature "Submitting the form" do
+ background do
+ @secret_phrase = "44-massive-knishes"
+ ThirtyOne::RandomPhrase.stub! generate: @secret_phrase
end
- describe 'on POST /parties' do
- it "creates a new party"
+ scenario "Registering as a new party" do
+ visit "/register"
+ fill_in "party[name]", with: "David Nemesis"
+ fill_in "party[email]", with: "david@example.org"
+ check "datetime_1203.8p"
+ click_button "Save the date"
- context "with invalid parameters" do
- it "displays an error message"
+ page.should have_css("div.thanks .party-info")
+ within(".party-info .secret-url") do
+ page.should have_content("party/#{@secret_phrase}")
end
end
- describe "on GET /party/:id" do
- it 'renders the form'
+ scenario "Fixing problems with a registration" do
+ visit "/register"
+ fill_in "party[name]", with: "David Nemesis"
+ fill_in "party[email]", with: "david@example.org"
+ click_button "Save the date"
+
+ page.should have_css(".error-messages")
+ page.should have_content("You have to choose at least one time when you're available to par-tay")
+
+ check "datetime_1203.6p"
+ check "datetime_1203.8p"
+ click_button "Save the date"
+
+ page.should have_css("div.thanks .party-info")
end
+end
- describe "on POST /party/:id" do
- it 'saves changes to the party'
+feature "Editing a response" do
+ background do
+ @party = FactoryGirl.create(:party)
+ end
+
+ scenario "Viewing my responses" do
+ visit "/party/#{@party.unique_phrase}"
+ page.should have_field "Your name", with: @party.name
+ page.should have_field "Your email address", with: @party.email
+ page.should have_checked_field "datetime_1203.8p"
+ end
+
+ scenario "Changing my response" do
+ visit "/party/#{@party.unique_phrase}"
+ fill_in "Your name", with: "Arnold Palmer"
+ click_button "Save the date"
+
+ # Now should be redirected back to this page with the new values
+ page.should have_field "Your name", with: "Arnold Palmer"
end
+
end
View
@@ -9,6 +9,17 @@
load(schema_file)
end
+require 'factory_girl'
+FactoryGirl.define do
+ sequence(:email) { |x| "user#{x}@example.com" }
+
+ factory :party, :class => ThirtyOne::Party do
+ name "Owen Wilson"
+ email
+ bits ["datetime_1203.8p"]
+ end
+end
+
RSpec.configure do |c|
c.before(:suite) do
quietly do
View
@@ -25,6 +25,8 @@ def self.all
end
class RandomPhrase
+ # Internal: Returns the number of possible values the random
+ # phrase generator could return, as an Integer.
def self.entropy
97 * (ADJECTIVES.length * NOUNS.length)
end
@@ -70,6 +72,10 @@ def self.entropy
"jovially", "merrily", "cordially", "easily"
]
+ # Public: Generates a more or less random String consisting of
+ # a number between 2 and 99, an English adjective, and an English
+ # plural noun, to be used as a friendly yet still somewhat opaque
+ # unique identifier for DB records, i.e. Parties
def self.generate
[].tap do |arr|
arr << (rand(97)+2).to_s
@@ -79,18 +85,28 @@ def self.generate
end.join("-")
end
+ # Internal: Fetches a random String value from one of the
+ # dictionary constants defined above. This is its own method
+ # so its can be tested, and stubbed, more easily.
+ # See also random_phrase_spec.rb.
def self.get_random_value(collection)
const = "#{self}::#{collection.to_s.upcase}".constantize
const[rand(const.length)]
end
end
+ # Abstract superclass for all ActiveRecord models provided by this
+ # mini-app, just in case. (In case of what? I dunno. This is my app.
+ # Go make your own if you'd have done it differently.)
class Model < ::ActiveRecord::Base
self.abstract_class = true
end
class Party < Model
has_many :party_bits
+
+ validate :name, presence: true
+ validate :email, presence: true
def bits
@bits ||= get_bits!
@@ -109,6 +125,13 @@ def bits=(bit_list)
def to_param
unique_phrase || id
end
+
+ before_validation :ensure_datetime_bits
+ def ensure_datetime_bits
+ if !bits.any? { |b| b =~ /^datetime/ }
+ errors[:base] << "You have to choose at least one time when you're available to par-tay"
+ end
+ end
# Need to save bits after save
after_save :update_bits
@@ -167,9 +190,9 @@ def bit_to_string(namespace, value)
end
get '/backend/parties' do
- halt 401
- # @parties = Party.order('id ASC').all
- # erb :all_parties
+ # halt 401
+ @parties = Party.order('id ASC').all
+ erb :list_parties
end
post '/parties' do
@@ -203,7 +226,7 @@ def bit_to_string(namespace, value)
erb :thanks
end
- get '/new_party' do
+ get '/register' do
params['party'] ||= {}
params['party']['email'] ||= params['email']
@party = Party.new(params['party'])
@@ -214,7 +237,7 @@ def bit_to_string(namespace, value)
if session[:secret_party_id]
redirect to("/party/#{session[:secret_party_id]}")
else
- redirect to("/new_party")
+ redirect to("/register")
end
end
View
@@ -13,6 +13,20 @@
</p>
</header>
+ <% if @party.errors.any? %>
+ <div class="error-messages">
+ <h3>Sorry, there was a problem with your form.</h3>
+ <p>Please fix them and try again.</p>
+ <ul>
+ <% @party.errors.full_messages.each do |msg| %>
+ <li class="error">
+ <%= msg %>
+ </li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+
<form action="<%= @party.persisted? ? url("/party/#{@party.unique_phrase}") : url("/parties") %>" method="post">
<section class="section row email-section">
<div class="span4 offset1 section-info">
@@ -22,12 +36,18 @@
<div class="section-body">
<div class="field" id="party-name">
- <input type="text" name="party[name]" class="xlarge span7" placeholder="Gene Simmons" value="<%= @party.name %>">
+ <label for="name-input">
+ Your name
+ </label>
+ <input type="text" id="name-input" name="party[name]" class="xlarge span7" placeholder="Gene Simmons" value="<%= @party.name %>">
<p class="help-block">This field is <strong>required</strong>. Cookies <strong>are</strong> delicious.</p>
</div>
<div class="field" id="party-email">
- <input type="text" name="party[email]" class="xlarge span7" placeholder="gene@kissarmy.net" value="<%= @party.email %>">
+ <label for="email-input">
+ Your email address
+ </label>
+ <input type="text" id="email-input" name="party[email]" class="xlarge span7" placeholder="gene@kissarmy.net" value="<%= @party.email %>">
<p class="help-block">This field is <strong>required</strong>. It <strong>must</strong> be a valid email address. The European debt crisis <strong>is</strong> complicated.</p>
</div>
@@ -73,7 +93,7 @@
<% [6,8,10].each do |hour| %>
<li>
<label data-bind="css: { 'checked': (bits().indexOf('<%= datetime_key_path(day, hour) %>') > -1) }">
- <input type="checkbox" name="party[bits][]" value="<%= datetime_key_path(day, hour) %>" data-bind="checked: bits" <%= 'checked' if @party.bits.include?(datetime_key_path(day, hour)) %>>
+ <input type="checkbox" name="party[bits][]" value="<%= datetime_key_path(day, hour) %>" id="<%= datetime_key_path(day, hour) %>" data-bind="checked: bits" <%= 'checked' if @party.bits.include?(datetime_key_path(day, hour)) %>>
<span class="label-text"><%= time_range(hour) %></span>
</label>
</li>
View
@@ -0,0 +1,38 @@
+<div class="backend list-parties">
+ <table>
+ <thead><tr>
+ <th>Name</th>
+ <th>Email</th>
+ <th>Secret URL</th>
+ <th>&nbsp;</th>
+ </tr></thead>
+ <tbody>
+ <% @parties.each do |party| %>
+ <tr>
+ <td class="name"><%= party.name %></td>
+ <td class="email">
+ <a href="mailto:<%= party.email %>">
+ <span><%= party.email %></span>
+ </a>
+ </td>
+ <td class="secret_url">
+ <a href="<%= url("/party/#{party.unique_phrase}") %>">
+ <span><%= url("/party/#{party.unique_phrase}") %></span>
+ </a>
+ </td>
+ <td class="actions">
+ <a href="<%= url("/party/#{party.unique_phrase}") %>" class="btn view"><span>View</span></a>
+ <form action="<%= url("/delete") %>" method="post" class="delete-form">
+ <input type="hidden" name="party_id" value="<%= party.unique_phrase %>" />
+ <button type="submit" class="btn delete">
+ <span>Delete</span>
+ </button>
+ </form>
+ </td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+
+
+</div>

0 comments on commit 2f64a24

Please sign in to comment.