Skip to content
Browse files

Merge branch 'release/0.4.12'

  • Loading branch information...
2 parents 8ce1f05 + f8d412f commit f69246266562a4948157299651afdc93e11adf49 @jeffkreeftmeijer jeffkreeftmeijer committed Sep 25, 2011
View
1 Gemfile
@@ -34,6 +34,7 @@ gem 'arnold', :git => 'git://github.com/codebrawl/arnold.git', :branch => 'devel
group :test do
gem 'rspec-rails'
+ gem 'shoulda-matchers'
gem 'capybara', :git => 'git://github.com/jnicklas/capybara.git', :ref => '549e6733'
gem 'launchy'
View
2 Gemfile.lock
@@ -253,6 +253,7 @@ GEM
ffi (>= 1.0.7)
json_pure
rubyzip
+ shoulda-matchers (1.0.0.beta3)
spork (0.9.0.rc7)
sprockets (2.0.0)
hike (~> 1.2)
@@ -312,6 +313,7 @@ DEPENDENCIES
rpm_contrib
rspec-rails
sass-rails
+ shoulda-matchers
spork (~> 0.9.0.rc)
thin
timecop
View
3 app/assets/stylesheets/application.css.sass
@@ -306,6 +306,9 @@ form
.tip a
font-size: 100%
+ #contests
+ margin-bottom: -10px
+
#entries, #articles
margin-bottom: -20px
View
13 app/controllers/contests_controller.rb
@@ -1,7 +1,6 @@
class ContestsController < ApplicationController
- def index
- return redirect_to root_path if request.path == '/contests'
+ def index
@contests = Contest.active
respond_to do |format|
@@ -11,13 +10,9 @@ def index
end
def show
- not_found unless @contest = Contest.find_by_slug(params[:id])
-
- if current_user
- @voted_entries = @contest.voted_entries(current_user)
- @entry = @contest.entries.where(:user_id => current_user.id).first
- end
- @voted_entries ||= []
+ @contest = Contest.by_slug(params[:id])
+ @entry = @contest.entries.by_user(current_user)
+ @voted_entries = @contest.voted_entries(current_user)
end
end
View
10 app/controllers/entries_controller.rb
@@ -2,14 +2,10 @@ class EntriesController < ApplicationController
before_filter :authenticate_user!, :only => :new
def new
- @contest = Contest.find_by_slug(params[:contest_id])
- not_found unless @contest && @contest.open?
-
- if @contest.has_entry_from?(current_user)
- redirect_to @contest, :alert => 'You already have an entry for this contest.'
- end
-
+ @contest = Contest.by_slug(params[:contest_id]).if_open
@entry = @contest.entries.new
+
+ @contest.not_found if @contest.has_entry_from?(current_user)
end
def create
View
7 app/controllers/homepage_controller.rb
@@ -0,0 +1,7 @@
+class HomepageController < ApplicationController
+
+ def index
+ @contests = Contest.active[0..1]
+ end
+
+end
View
14 app/models/contest.rb
@@ -1,5 +1,6 @@
require 'state'
require 'time_from_date_field'
+require 'mongoid_extensions'
class Contest
include Mongoid::Document
@@ -19,7 +20,7 @@ class Contest
include TimeFromDateField
include State
- validates :user, :name, :description, :starting_on, :presence => true
+ validates :user, :name, :description, :starting_on, :tagline, :presence => true
validates :tagline, :length => { :minimum => 50 }
before_create :set_voting_and_closing_dates
@@ -35,6 +36,15 @@ def self.active
scoped.order_by([:starting_on, :desc]).reject { |c| c.pending? }
end
+ def self.by_slug(slug)
+ contest = first(:conditions => {:slug => slug})
+ contest || raise(Mongoid::Errors::DocumentNotFound.new(Contest, slug))
+ end
+
+ def if_open
+ open? ? self : not_found
+ end
+
def set_voting_and_closing_dates
self.voting_on = starting_on + 1.week if self.voting_on.blank?
self.closing_on = voting_on + 1.week if self.closing_on.blank?
@@ -59,7 +69,7 @@ def has_entry_from?(user)
end
def voted_entries(user)
- entries.select { |e| e.votes_from?(user) }
+ user ? entries.select { |e| e.votes_from?(user) } : []
end
end
View
4 app/models/entry.rb
@@ -14,6 +14,10 @@ class Entry
embeds_many :comments
belongs_to :user
+ def self.by_user(user)
+ user ? first(:conditions => {:user_id => user.id}) : nil
+ end
+
def votes_from?(user)
votes.where(:user_id => user.id).any?
end
View
11 app/views/contests/index.haml
@@ -1,11 +1,2 @@
-- content_for(:description){ 'Codebrawl, a code contest website focussed on the Ruby programming language and open source software.' }
-
-- unless @contests.map(&:state).include? 'open'
- %section.tip
- %h1 Get ready for next week's contest!
- %p
- :erb
- Our next contest will start next Monday at 14:00 (UTC). If you want to be sure you don't miss it, just subscribe to our <%= link_to 'contests feed', 'http://feeds.feedburner.com/codebrawl' %>. Also, don't forget to check out and vote for the entries in <%= link_to "last week's contest", @contests.first %>.
-
#contests
- = render @contests
+ = render @contests
View
7 app/views/contests/show.haml
@@ -34,13 +34,6 @@
%p
:erb
You can keep updating your gist, we'll take a snapshot of it when the voting period begins. If you want, you can always <%= link_to "delete your entry", [@contest, @entry], :method => :delete %>.
-
- %h3
- :erb
- You entered <%= link_to "gist #{@entry.gist_id}", "https://gist.github.com/#{@entry.gist_id}" %>
- %p
- :erb
- You can keep updating your gist, we'll take a snapshot of it when the voting period begins. If you want, you can always <%= link_to "delete your entry", [@contest, @entry], :method => :delete %>.
- if @contest.finished?
.message
%h3 This contest is finished
View
13 app/views/homepage/index.haml
@@ -0,0 +1,13 @@
+- content_for(:description){ 'Codebrawl, a code contest website focussed on the Ruby programming language and open source software.' }
+
+- unless @contests.map(&:state).include? 'open'
+ %section.tip
+ %h1 Get ready for next week's contest!
+ %p
+ :erb
+ Our next contest will start next Monday at 14:00 (UTC). If you want to be sure you don't miss it, just subscribe to our <%= link_to 'contests feed', 'http://feeds.feedburner.com/codebrawl' %>. Also, don't forget to check out and vote for the entries in <%= link_to "last week's contest", @contests.first %>.
+
+#contests
+ = render @contests
+
+= link_to 'Contest archive', contests_path
View
2 app/views/layouts/application.haml
@@ -25,7 +25,7 @@
%nav
%ul
- %li= link_to 'Contests', :root
+ %li= link_to 'Contests', :contests
%li= link_to 'Hall of Fame', :users
//%li= link_to 'News', :articles
%li.user
View
2 config/routes.rb
@@ -20,6 +20,6 @@
get '/rules' => "application#rules", :as => 'rules'
- root :to => 'contests#index'
+ root :to => 'homepage#index'
end
View
9 lib/mongoid_extensions.rb
@@ -0,0 +1,9 @@
+module MongoidExtensions
+
+ def not_found
+ raise Mongoid::Errors::DocumentNotFound.new(self.class, id)
+ end
+
+end
+
+Mongoid::Document.send(:include, MongoidExtensions)
View
174 spec/acceptance/contest_index_spec.rb
@@ -1,162 +1,48 @@
require 'acceptance/acceptance_helper'
-feature 'Homepage' do
+feature 'Contest index' do
- scenario 'be redirected to the homepage when accessing /contests' do
- # TODO: Move this one to a controller spec
- visit '/contests'
- URI.parse(current_url).path.should == '/'
- end
-
- context "on the homepage" do
-
- background :all do
- @voting = Fabricate(
+ background(:all) do
+ VCR.use_cassette('existing_gist') do
+ Fabricate(
:contest,
:name => 'Fun with ChunkyPNG',
- :tagline => 'Having a bit of with image manipulation in ChunkyPNG',
- :voting_on => Date.yesterday.to_time
- )
- VCR.use_cassette('existing_gist') do
- @finished = Fabricate(
- :contest,
- :name => 'Improving Ruby',
- :tagline => 'Build verything you ever wanted, monkey-patched into Ruby',
- :entries => [Fabricate.build(:entry_with_files, :user => Fabricate(:user, :login => 'bob'))] * 3,
- :closing_on => Date.yesterday.to_time
- )
- end
- @pending = Fabricate(
- :contest,
- :name => 'RSpec extensions',
- :tagline => 'Giving back to RSpec by building the funniest or most useful RSpec formatter',
- :starting_on => Date.tomorrow.to_time
+ :tagline => 'Having a bit of fun with image manipulation in ChunkyPNG',
+ :closing_on => Date.yesterday.to_time,
+ :entries => [
+ Fabricate.build(
+ :entry_with_files,
+ :user => Fabricate(:user, :login => 'bob')
+ )
+ ]
)
-
- visit '/'
- end
-
- scenario 'see the "no open contests"-message' do
- within('.tip') do
- page.should have_content "Get ready for next week's contest"
- page.should have_content 'Our next contest will start next Monday at 14:00 (UTC)'
- page.should have_link 'contests feed'
- body.should include 'href="http://feeds.feedburner.com/codebrawl"'
- page.should have_link "last week's contest"
- body.should include 'href="/contests/fun-with-chunkypng"'
- end
end
- context 'when having an open contest' do
-
- background :all do
- @user = Fabricate(:user)
- VCR.use_cassette('existing_gist') do
- @open = Fabricate(
- :contest,
- :name => 'Euler #74',
- :tagline => 'Get your Euler on and build the fastest solution to problem #123',
- :starting_on => Date.yesterday.to_time,
- :entries => [Fabricate.build(:entry_with_files, :user => Fabricate(:user, :login => 'bob'))]
- )
- end
- end
-
- before { visit '/' }
-
- scenario 'see the Codebrawl header' do
- page.should have_content 'Codebrawl'
- end
-
- scenario 'do not see the "no open contests"-message' do
- page.should have_no_content "Get ready for next week's contest"
- end
-
- scenario 'return to the homepage after clicking the header' do
- click_link 'Fun with ChunkyPNG'
- click_link 'Codebrawl'
- ['Euler #74', 'Fun with ChunkyPNG'].each do |name|
- page.should have_link name
- end
- end
-
- scenario 'return to the homepage after clicking the "Contests" menu item' do
- click_link 'Fun with ChunkyPNG'
- click_link 'Contests'
- ['Euler #74', 'Fun with ChunkyPNG'].each do |name|
- page.should have_link name
- end
- end
-
- scenario 'see a list of contest names' do
- ['Euler #74', 'Fun with ChunkyPNG', 'Improving Ruby'].each do |name|
- page.should have_link name
- end
-
- page.should have_no_content 'RSpec extensions'
- end
-
- scenario 'see entry counts in the contests list' do
- page.should have_content "1 entry already"
- end
-
- scenario 'see the contest taglines' do
- ['Get your Euler on and build the fastest solution to problem #123', 'Having a bit of with image manipulation in ChunkyPNG', 'Build verything you ever wanted, monkey-patched into Ruby'].each do |tagline|
- page.should have_content tagline
- end
- end
-
- scenario 'see the contest states' do
- within "#contest_#{@open.id}" do
- page.should have_content 'Open'
- end
-
- within "#contest_#{@voting.id}" do
- page.should have_content 'Voting'
- end
-
- within "#contest_#{@finished.id}" do
- page.should have_content 'Finished'
- end
- end
-
- scenario 'see the contest winners avatars and medals' do
- within "#contest_#{@finished.id}" do
- page.should have_css('img.medal')
- page.should have_css('img.gravatar')
- end
- end
-
- scenario "visit the winner's entry" do
- within "#contest_#{@finished.id}" do
- page.find(:xpath, "//ol[@class='winners']//a[1]").click
- end
- page.should have_content "This contest is finished"
- end
+ visit '/contests'
- scenario 'visit the submissions page' do
- click_link 'Submit a contest idea'
- page.should have_content 'Submit your contest idea'
- end
+ end
- scenario 'visit the hall of fame' do
- click_link 'Hall of Fame'
- within('#main') { page.should have_content 'Hall of Fame' }
- end
+ scenario 'see links to the contests' do
+ page.should have_link 'Fun with ChunkyPNG'
+ end
- context 'after logging in' do
+ scenario 'see the contest taglines' do
+ page.should have_content 'Having a bit of fun with image manipulation in ChunkyPNG'
+ end
- background { login_via_github }
+ scenario 'see the contest states' do
+ page.should have_content 'Finished'
+ end
- scenario 'visit my profile page' do
- click_link 'charlie'
- page.should have_content 'Total points'
- end
+ scenario 'see the contest winners' do
+ page.should have_css('ol.winners li a img.gravatar')
+ end
- end
+ scenario 'click a contest winner avatar' do
+ find('ol.winners li a').click
+ page.should have_content 'This contest is finished'
+ end
- end
- end
end
View
3 spec/acceptance/contests_spec.rb
@@ -53,9 +53,10 @@
scenario 'see the "not found"-page' do
lambda{
visit '/contests/terminal-admin'
- }.should raise_error ActionController::RoutingError
+ }.should raise_error Mongoid::Errors::DocumentNotFound
end
+
end
context 'on a contest page' do
View
27 spec/acceptance/entries_spec.rb
@@ -13,30 +13,6 @@
)
end
- context 'on the new entry form or a contest that does not exist' do
-
- scenario 'see the "not found"-page' do
- lambda{
- visit '/contests/terminal-admin/entries/new'
- }.should raise_error ActionController::RoutingError
- end
-
- end
-
- context 'on the new entry form or a contest that is closed for entries' do
-
- background do
- @contest = Fabricate(:contest, :voting_on => Date.yesterday.to_time, :name => 'Terminal admin')
- end
-
- scenario 'see the "not found"-page' do
- lambda{
- visit '/contests/terminal-admin/entries/new'
- }.should raise_error ActionController::RoutingError
- end
-
- end
-
context 'on the new entry form' do
background { visit "/contests/#{@contest.slug}/entries/new" }
@@ -81,8 +57,7 @@
end
scenario 'fail to add another entry' do
- click_link 'Enter'
- page.should have_content 'You already have an entry for this contest.'
+ expect { click_link 'Enter' }.to raise_error Mongoid::Errors::DocumentNotFound
end
context 'when logged in' do
View
107 spec/acceptance/homepage_spec.rb
@@ -0,0 +1,107 @@
+require 'acceptance/acceptance_helper'
+
+feature 'Homepage' do
+
+ context "on the homepage" do
+
+ background :all do
+ @voting = Fabricate(
+ :contest,
+ :name => 'Fun with ChunkyPNG',
+ :tagline => 'Having a bit of with image manipulation in ChunkyPNG',
+ :voting_on => Date.yesterday.to_time
+ )
+ VCR.use_cassette('existing_gist') do
+ @finished = Fabricate(
+ :contest,
+ :name => 'Improving Ruby',
+ :tagline => 'Build verything you ever wanted, monkey-patched into Ruby',
+ :entries => [Fabricate.build(:entry_with_files, :user => Fabricate(:user, :login => 'bob'))] * 3,
+ :closing_on => Date.yesterday.to_time
+ )
+ end
+ @pending = Fabricate(
+ :contest,
+ :name => 'RSpec extensions',
+ :tagline => 'Giving back to RSpec by building the funniest or most useful RSpec formatter',
+ :starting_on => Date.tomorrow.to_time
+ )
+
+ visit '/'
+ end
+
+ scenario 'see the "no open contests"-message' do
+ within('.tip') do
+ page.should have_content "Get ready for next week's contest"
+ page.should have_content 'Our next contest will start next Monday at 14:00 (UTC)'
+ page.should have_link 'contests feed'
+ body.should include 'href="http://feeds.feedburner.com/codebrawl"'
+ page.should have_link "last week's contest"
+ body.should include 'href="/contests/fun-with-chunkypng"'
+ end
+ end
+
+ context 'when having an open contest' do
+
+ background :all do
+ @user = Fabricate(:user)
+ VCR.use_cassette('existing_gist') do
+ @open = Fabricate(
+ :contest,
+ :name => 'Euler #74',
+ :tagline => 'Get your Euler on and build the fastest solution to problem #123',
+ :starting_on => Date.yesterday.to_time,
+ :entries => [Fabricate.build(:entry_with_files, :user => Fabricate(:user, :login => 'bob'))]
+ )
+ end
+ end
+
+ before { visit '/' }
+
+ scenario 'do not see the "no open contests"-message' do
+ page.should have_no_content "Get ready for next week's contest"
+ end
+
+ scenario 'see a list of contest names' do
+ ['Euler #74', 'Fun with ChunkyPNG'].each do |name|
+ page.should have_link name
+ end
+
+ page.should have_no_content 'RSpec extensions'
+ end
+
+ scenario 'only show two contests at once' do
+ page.should have_no_content 'Improving Ruby'
+ end
+
+ scenario 'see entry counts in the contests list' do
+ page.should have_content "1 entry already"
+ end
+
+ scenario 'see the contest taglines' do
+ ['Get your Euler on and build the fastest solution to problem #123', 'Having a bit of with image manipulation in ChunkyPNG'].each do |tagline|
+ page.should have_content tagline
+ end
+ end
+
+ scenario 'visit the contest archive' do
+ click_link 'Contest archive'
+ page.should have_content 'Improving Ruby'
+ end
+
+ context 'after logging in' do
+
+ background { login_via_github }
+
+ scenario 'visit my profile page' do
+ click_link 'charlie'
+ page.should have_content 'Total points'
+ end
+
+ end
+
+ end
+
+ end
+
+end
View
27 spec/acceptance/menu_spec.rb
@@ -0,0 +1,27 @@
+require 'acceptance/acceptance_helper'
+
+feature 'Menu' do
+
+ background { visit '/rules' }
+
+ scenario 'return to the homepage after clicking the header' do
+ click_link 'Codebrawl'
+ current_path.should == '/'
+ end
+
+ scenario 'go to the contest archive after clicking the "Contests" menu item' do
+ click_link 'Contests'
+ current_path.should == '/contests'
+ end
+
+ scenario 'visit the submissions page' do
+ click_link 'Submit a contest idea'
+ current_path.should == '/submissions/new'
+ end
+
+ scenario 'visit the hall of fame' do
+ click_link 'Hall of Fame'
+ current_path.should == '/users'
+ end
+
+end
View
39 spec/lib/mongoid_extensions_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_config'
+
+module Mongoid
+ module Document; end
+
+ module Errors
+ class MongoidError < StandardError; end
+
+ class DocumentNotFound < MongoidError
+ def initialize(*args); end
+ end
+ end
+end
+
+require File.expand_path('lib/mongoid_extensions.rb')
+
+class ExtendedDocument
+ include Mongoid::Document
+end
+
+describe MongoidExtensions do
+
+ let(:object) do
+ object = ExtendedDocument.new
+ object.stubs(:id).returns(123)
+ object
+ end
+
+ describe '#not_found' do
+
+ subject { object.not_found }
+
+ it 'should raise a DocumentNotFound error' do
+ expect { subject }.to raise_error Mongoid::Errors::DocumentNotFound
+ end
+
+ end
+
+end
View
137 spec/models/contest_spec.rb
@@ -2,6 +2,18 @@
describe Contest do
+ it { should validate_presence_of(:name) }
+
+ it { should validate_presence_of(:description) }
+
+ it { should validate_presence_of(:starting_on) }
+
+ it { should validate_presence_of(:user) }
+
+ it { should validate_presence_of(:tagline) }
+
+ it { should ensure_length_of(:tagline).is_at_least(50) }
+
context '.not_open' do
subject { Contest.not_open }
@@ -17,76 +29,111 @@
end
- context '#save!' do
+ context '.by_slug' do
- context 'when keeping all fields empty' do
+ it 'should raise a DocumentNotFound error if the contest does not exist' do
+ expect {
+ Contest.by_slug('slug')
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
+ end
- it { should have(1).error_on(:name) }
+ context 'when the contest exists' do
- it { should have(1).error_on(:description) }
+ subject { Contest.by_slug('slug') }
- it { should have(1).error_on(:starting_on) }
+ let(:contest) { Fabricate(:contest, :name => 'slug') }
- it { should have(1).error_on(:user) }
+ before { contest }
- it { should have(1).error_on(:tagline ) }
+ it 'should return the contest' do
+ should == contest
+ end
end
- context 'when creating a valid contest' do
- around do |example|
- Timecop.travel(Time.parse('May 23 2011 10:00 UTC')) { example.run }
- end
+ end
- subject { Fabricate(:contest) }
+ context 'if_open' do
- it { should be_pending }
+ let(:contest) { Contest.new }
- it { should have_a_starting_date_of Date.parse('May 23 2011') }
+ before { contest.stubs(:open?).returns(false) }
- it { should have_a_voting_date_of Date.parse('May 30 2011') }
+ subject { contest.if_open }
- it { should have_a_closing_date_of Date.parse('June 6 2011') }
+ it 'should raise an error if the contest is not open' do
+ expect { subject }.to raise_error Mongoid::Errors::DocumentNotFound
+ end
- context 'after 4PM, UTC' do
+ context 'with an open contest' do
- around { |example| Timecop.travel(Time.parse('May 23 2011 18:00 UTC')) { example.run } }
+ before { contest.stubs(:open?).returns(true) }
- it { should be_open }
+ it 'should not raise an error if the contest is not open' do
+ expect { subject }.not_to raise_error
+ end
+ it 'should return the contest' do
+ should == contest
end
- context 'after seven days, before 4PM, UTC' do
+ end
- around { |example| Timecop.travel(Time.parse('May 30 2011 11:00 UTC')) { example.run } }
+ end
- it { should be_open }
+ context '#save!' do
- end
+ around do |example|
+ Timecop.travel(Time.parse('May 23 2011 10:00 UTC')) { example.run }
+ end
- context 'after seven days, after 4PM, UTC' do
+ subject { Fabricate(:contest) }
- around { |example| Timecop.travel(Time.parse('May 30 2011 17:00 UTC')) { example.run } }
+ it { should be_pending }
- it { should be_voting }
+ it { should have_a_starting_date_of Date.parse('May 23 2011') }
- end
+ it { should have_a_voting_date_of Date.parse('May 30 2011') }
- context 'after fourteen days, before 4PM, UTC' do
+ it { should have_a_closing_date_of Date.parse('June 6 2011') }
- around { |example| Timecop.travel(Time.parse('June 6 2011 11:00 UTC')) { example.run } }
+ context 'after 4PM, UTC' do
- it { should be_voting }
+ around { |example| Timecop.travel(Time.parse('May 23 2011 18:00 UTC')) { example.run } }
- end
+ it { should be_open }
- context 'after fourteen days, after 4PM, UTC' do
+ end
- around { |example| Timecop.travel(Time.parse('June 6 2011 17:00 UTC')) { example.run } }
+ context 'after seven days, before 4PM, UTC' do
- it { should be_finished }
+ around { |example| Timecop.travel(Time.parse('May 30 2011 11:00 UTC')) { example.run } }
- end
+ it { should be_open }
+
+ end
+
+ context 'after seven days, after 4PM, UTC' do
+
+ around { |example| Timecop.travel(Time.parse('May 30 2011 17:00 UTC')) { example.run } }
+
+ it { should be_voting }
+
+ end
+
+ context 'after fourteen days, before 4PM, UTC' do
+
+ around { |example| Timecop.travel(Time.parse('June 6 2011 11:00 UTC')) { example.run } }
+
+ it { should be_voting }
+
+ end
+
+ context 'after fourteen days, after 4PM, UTC' do
+
+ around { |example| Timecop.travel(Time.parse('June 6 2011 17:00 UTC')) { example.run } }
+
+ it { should be_finished }
end
@@ -212,12 +259,24 @@
let(:entry) { Fabricate.build(:entry) }
let(:contest) { entry.contest }
- before { entry.stubs(:votes_from?).with(user).returns(true) }
+ context 'when not passing a user' do
- subject { contest.voted_entries(user) }
+ subject { contest.voted_entries(nil) }
+
+ it { should == [] }
+
+ end
+
+ context 'when passing a user with votes' do
+
+ before { entry.stubs(:votes_from?).with(user).returns(true) }
+
+ subject { contest.voted_entries(user) }
+
+ it 'returns entries the user has voted on' do
+ should == [entry]
+ end
- it 'returns entries the user has voted on' do
- should == [entry]
end
end
View
60 spec/models/entry_spec.rb
@@ -2,6 +2,44 @@
describe Entry do
+ it { should validate_presence_of(:user) }
+
+ it { should validate_presence_of(:gist_id) }
+
+ describe '.by_user' do
+
+ let(:entry) { Fabricate(:entry) }
+ let(:user) { entry.user }
+ let(:contest) { entry.contest }
+
+ context 'when not passing a user' do
+
+ subject { contest.entries.by_user(nil) }
+
+ it { should be_nil }
+
+ end
+
+ context 'when providing a user that has no entries' do
+
+ subject { contest.entries.by_user(User.new) }
+
+ it { should be_nil }
+
+ end
+
+ context 'when passing a user that has an entry' do
+
+ subject { contest.entries.by_user(user) }
+
+ it 'should return the entry' do
+ should == entry
+ end
+
+ end
+
+ end
+
describe '#votes_from?' do
let(:entry) { Fabricate(:entry) }
let(:user) { Fabricate(:user) }
@@ -19,18 +57,6 @@
end
- context '#save!' do
-
- context 'when keeping all fields empty' do
-
- it { should have(1).error_on(:user) }
-
- it { should have(1).error_on(:gist_id) }
-
- end
-
- end
-
context '#contest' do
it 'should have a contest' do
@@ -58,16 +84,6 @@
end
- context '.save!' do
-
- context 'when keeping all fields empty' do
-
- it { should have(1).error_on(:user) }
-
- end
-
- end
-
context '#score' do
context 'when the score attribute is set' do
View
7 spec/models/user_spec.rb
@@ -0,0 +1,7 @@
+require 'spec_helper'
+
+describe User do
+
+ it { should validate_presence_of(:login) }
+
+end
View
29 spec/spec_config.rb
@@ -1,3 +1,32 @@
+class DeferredGarbageCollection
+
+ DEFERRED_GC_THRESHOLD = (ENV['DEFER_GC'] || 15.0).to_f
+
+ @@last_gc_run = Time.now
+
+ def self.start
+ GC.disable if DEFERRED_GC_THRESHOLD > 0
+ end
+
+ def self.reconsider
+ if DEFERRED_GC_THRESHOLD > 0 && Time.now - @@last_gc_run >= DEFERRED_GC_THRESHOLD
+ GC.enable
+ GC.start
+ GC.disable
+ @@last_gc_run = Time.now
+ end
+ end
+end
+
RSpec.configure do |config|
config.mock_with :mocha
+
+ config.before(:all) do
+ DeferredGarbageCollection.start
+ end
+
+ config.after(:all) do
+ DeferredGarbageCollection.reconsider
+ end
+
end
View
7 spec/support/validations.rb
@@ -0,0 +1,7 @@
+module ::ActiveModel::Validations
+ def errors_on(attribute)
+ self.valid?
+ [self.errors[attribute]].flatten.compact
+ end
+ alias :error_on :errors_on
+end
View
2 spec/validators/gist_validator_spec.rb
@@ -1,6 +1,6 @@
require 'spec_config'
require 'active_model'
-require 'rspec/rails/extensions'
+require 'support/validations'
require File.expand_path('app/validators/gist_validator')

0 comments on commit f692462

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